Browse Source

2007-10-12 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	Implemented BitTorrent/http/ftp integrated download.
	I've rewritten lots of files and now some headers have forward
	class declarations to reduce compile time.
	The implementation is extremely alpha stage, I recommend to use this
	for testing purpose only.
Tatsuhiro Tsujikawa 18 years ago
parent
commit
048a2cf597
100 changed files with 2546 additions and 1394 deletions
  1. 8 0
      ChangeLog
  2. 6 1
      TODO
  3. 10 10
      configure
  4. 1 1
      configure.ac
  5. 1 1
      po/Makefile.in
  6. 1 0
      po/POTFILES
  7. 1 0
      po/POTFILES.in
  8. 176 24
      src/AbstractCommand.cc
  9. 25 7
      src/AbstractCommand.h
  10. 33 20
      src/AbstractDiskWriter.cc
  11. 11 23
      src/AbstractDiskWriter.h
  12. 3 0
      src/AbstractProxyRequestCommand.cc
  13. 3 1
      src/AbstractProxyRequestCommand.h
  14. 5 0
      src/AbstractProxyResponseCommand.cc
  15. 3 1
      src/AbstractProxyResponseCommand.h
  16. 23 6
      src/AbstractSingleDiskAdaptor.cc
  17. 16 8
      src/AbstractSingleDiskAdaptor.h
  18. 17 1
      src/ActivePeerConnectionCommand.cc
  19. 12 12
      src/ActivePeerConnectionCommand.h
  20. 2 2
      src/AlphaNumberDecorator.h
  21. 8 1
      src/AutoSaveCommand.cc
  22. 2 3
      src/AutoSaveCommand.h
  23. 52 0
      src/BinaryStream.h
  24. 22 30
      src/BtCheckIntegrityEntry.cc
  25. 51 0
      src/BtCheckIntegrityEntry.h
  26. 8 25
      src/BtContext.h
  27. 1 3
      src/BtContextAwareCommand.cc
  28. 4 3
      src/BtContextAwareCommand.h
  29. 83 0
      src/BtDependency.cc
  30. 22 19
      src/BtDependency.h
  31. 15 20
      src/BtFileAllocationEntry.cc
  32. 56 0
      src/BtFileAllocationEntry.h
  33. 2 2
      src/BtPieceMessage.cc
  34. 24 21
      src/BtPostDownloadHandler.cc
  35. 51 0
      src/BtPostDownloadHandler.h
  36. 0 2
      src/BtProgressInfoFile.h
  37. 62 65
      src/BtRegistry.cc
  38. 20 11
      src/BtRegistry.h
  39. 8 2
      src/BtRuntime.h
  40. 97 0
      src/BtSetup.cc
  41. 14 12
      src/BtSetup.h
  42. 17 15
      src/ByteArrayDiskWriter.cc
  43. 2 3
      src/ByteArrayDiskWriter.h
  44. 52 0
      src/ByteArrayDiskWriterFactory.h
  45. 9 21
      src/CheckIntegrityCommand.cc
  46. 4 3
      src/CheckIntegrityCommand.h
  47. 43 12
      src/CheckIntegrityEntry.cc
  48. 20 12
      src/CheckIntegrityEntry.h
  49. 72 0
      src/CheckIntegrityMan.cc
  50. 12 29
      src/CheckIntegrityMan.h
  51. 8 4
      src/ChecksumCommand.cc
  52. 2 2
      src/ChecksumCommand.h
  53. 5 0
      src/ChunkChecksum.h
  54. 2 0
      src/ChunkChecksumValidator.cc
  55. 0 210
      src/ConsoleDownloadEngine.cc
  56. 162 0
      src/ConsoleStatCalc.cc
  57. 14 10
      src/ConsoleStatCalc.h
  58. 8 3
      src/CopyDiskAdaptor.cc
  59. 3 2
      src/CopyDiskAdaptor.h
  60. 7 1
      src/DefaultBtContext.cc
  61. 19 1
      src/DefaultBtContext.h
  62. 198 93
      src/DefaultBtProgressInfoFile.cc
  63. 19 35
      src/DefaultBtProgressInfoFile.h
  64. 1 35
      src/DefaultDiskWriter.cc
  65. 2 3
      src/DefaultDiskWriter.h
  66. 52 0
      src/DefaultDiskWriterFactory.h
  67. 2 0
      src/DefaultPeerStorage.cc
  68. 157 83
      src/DefaultPieceStorage.cc
  69. 30 11
      src/DefaultPieceStorage.h
  70. 6 5
      src/DefaultSegmentManFactory.cc
  71. 2 1
      src/DefaultSegmentManFactory.h
  72. 14 2
      src/Dependency.h
  73. 5 2
      src/DirectDiskAdaptor.cc
  74. 2 1
      src/DirectDiskAdaptor.h
  75. 11 6
      src/DiskAdaptor.cc
  76. 11 7
      src/DiskAdaptor.h
  77. 5 25
      src/DiskWriter.h
  78. 9 10
      src/DiskWriterFactory.h
  79. 45 16
      src/DownloadCommand.cc
  80. 5 8
      src/DownloadCommand.h
  81. 99 0
      src/DownloadContext.h
  82. 75 2
      src/DownloadEngine.cc
  83. 48 35
      src/DownloadEngine.h
  84. 34 169
      src/DownloadEngineFactory.cc
  85. 13 18
      src/DownloadEngineFactory.h
  86. 23 0
      src/File.cc
  87. 2 0
      src/File.h
  88. 27 24
      src/FileAllocationCommand.cc
  89. 7 4
      src/FileAllocationCommand.h
  90. 18 5
      src/FileAllocationDispatcherCommand.cc
  91. 5 6
      src/FileAllocationDispatcherCommand.h
  92. 26 13
      src/FileAllocationEntry.cc
  93. 16 19
      src/FileAllocationEntry.h
  94. 56 0
      src/FileAllocationIterator.h
  95. 39 29
      src/FileAllocationMan.cc
  96. 14 38
      src/FileAllocationMan.h
  97. 14 1
      src/FileEntry.cc
  98. 2 12
      src/FileEntry.h
  99. 24 2
      src/FillRequestGroupCommand.cc
  100. 8 9
      src/FillRequestGroupCommand.h

+ 8 - 0
ChangeLog

@@ -1,3 +1,11 @@
+2007-10-12  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	Implemented BitTorrent/http/ftp integrated download.
+	I've rewritten lots of files and now some headers have forward
+	class declarations to reduce compile time.
+	The implementation is extremely alpha stage, I recommend to use this
+	for testing purpose only.
+
 2007-09-14  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 2007-09-14  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 
 	Fixed the compilation error on 64bit platform.
 	Fixed the compilation error on 64bit platform.

+ 6 - 1
TODO

@@ -47,4 +47,9 @@
 	src/PeerChokeCommand.h
 	src/PeerChokeCommand.h
 	src/TorrentAutoSaveCommand.h
 	src/TorrentAutoSaveCommand.h
 * Rewrite MetaFileUtil
 * Rewrite MetaFileUtil
-* Integrate FTP/HTTP/BitTorrent downloads from metalinks
+* Reconsider the use of RecoverableException and FatalException
+* Limit the number of opening file to,say,100 in MultiDiskAdaptor.
+
+* Implement duplicate download checking in Bt
+* Implement the feature to treat http/ftp as auxuality download method for BitTorrent
+* Fixed the download error when sending "CWD //*" to the ftp server

+ 10 - 10
configure

@@ -1,6 +1,6 @@
 #! /bin/sh
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for aria2c 0.11.3.
+# Generated by GNU Autoconf 2.61 for aria2c 0.12.0alpha.
 #
 #
 # Report bugs to <[email protected]>.
 # Report bugs to <[email protected]>.
 #
 #
@@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 # Identity of this package.
 PACKAGE_NAME='aria2c'
 PACKAGE_NAME='aria2c'
 PACKAGE_TARNAME='aria2c'
 PACKAGE_TARNAME='aria2c'
-PACKAGE_VERSION='0.11.3'
-PACKAGE_STRING='aria2c 0.11.3'
+PACKAGE_VERSION='0.12.0alpha'
+PACKAGE_STRING='aria2c 0.12.0alpha'
 PACKAGE_BUGREPORT='[email protected]'
 PACKAGE_BUGREPORT='[email protected]'
 
 
 ac_unique_file="src/Socket.h"
 ac_unique_file="src/Socket.h"
@@ -1298,7 +1298,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
   cat <<_ACEOF
-\`configure' configures aria2c 0.11.3 to adapt to many kinds of systems.
+\`configure' configures aria2c 0.12.0alpha to adapt to many kinds of systems.
 
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
 
@@ -1369,7 +1369,7 @@ fi
 
 
 if test -n "$ac_init_help"; then
 if test -n "$ac_init_help"; then
   case $ac_init_help in
   case $ac_init_help in
-     short | recursive ) echo "Configuration of aria2c 0.11.3:";;
+     short | recursive ) echo "Configuration of aria2c 0.12.0alpha:";;
    esac
    esac
   cat <<\_ACEOF
   cat <<\_ACEOF
 
 
@@ -1490,7 +1490,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
 if $ac_init_version; then
   cat <<\_ACEOF
   cat <<\_ACEOF
-aria2c configure 0.11.3
+aria2c configure 0.12.0alpha
 generated by GNU Autoconf 2.61
 generated by GNU Autoconf 2.61
 
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1504,7 +1504,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 running configure, to aid debugging if configure makes a mistake.
 
 
-It was created by aria2c $as_me 0.11.3, which was
+It was created by aria2c $as_me 0.12.0alpha, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
 
   $ $0 $@
   $ $0 $@
@@ -2300,7 +2300,7 @@ fi
 
 
 # Define the identity of the package.
 # Define the identity of the package.
  PACKAGE='aria2c'
  PACKAGE='aria2c'
- VERSION='0.11.3'
+ VERSION='0.12.0alpha'
 
 
 
 
 cat >>confdefs.h <<_ACEOF
 cat >>confdefs.h <<_ACEOF
@@ -14327,7 +14327,7 @@ exec 6>&1
 # report actual input values of CONFIG_FILES etc. instead of their
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 # values after options handling.
 ac_log="
 ac_log="
-This file was extended by aria2c $as_me 0.11.3, which was
+This file was extended by aria2c $as_me 0.12.0alpha, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_FILES    = $CONFIG_FILES
@@ -14380,7 +14380,7 @@ Report bugs to <[email protected]>."
 _ACEOF
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
 ac_cs_version="\\
-aria2c config.status 0.11.3
+aria2c config.status 0.12.0alpha
 configured by $0, generated by GNU Autoconf 2.61,
 configured by $0, generated by GNU Autoconf 2.61,
   with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
   with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
 

+ 1 - 1
configure.ac

@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 # Process this file with autoconf to produce a configure script.
 #
 #
 AC_PREREQ(2.59)
 AC_PREREQ(2.59)
-AC_INIT(aria2c, 0.11.3, [email protected])
+AC_INIT(aria2c, 0.12.0alpha, [email protected])
 AC_CANONICAL_HOST
 AC_CANONICAL_HOST
 AC_CANONICAL_SYSTEM
 AC_CANONICAL_SYSTEM
 AM_INIT_AUTOMAKE()
 AM_INIT_AUTOMAKE()

+ 1 - 1
po/Makefile.in

@@ -9,7 +9,7 @@
 # General Public License and is *not* in the public domain.
 # General Public License and is *not* in the public domain.
 
 
 PACKAGE = aria2c
 PACKAGE = aria2c
-VERSION = 0.11.3
+VERSION = 0.12.0alpha
 
 
 SHELL = /bin/sh
 SHELL = /bin/sh
 
 

+ 1 - 0
po/POTFILES

@@ -4,6 +4,7 @@
      ../src/TorrentRequestInfo.cc \
      ../src/TorrentRequestInfo.cc \
      ../src/UrlRequestInfo.cc \
      ../src/UrlRequestInfo.cc \
      ../src/main.cc \
      ../src/main.cc \
+     ../src/version_usage.cc \
      ../src/DefaultPieceStorage.cc \
      ../src/DefaultPieceStorage.cc \
      ../src/DefaultBtAnnounce.cc \
      ../src/DefaultBtAnnounce.cc \
      ../src/DefaultBtProgressInfoFile.cc \
      ../src/DefaultBtProgressInfoFile.cc \

+ 1 - 0
po/POTFILES.in

@@ -4,6 +4,7 @@ src/DownloadEngineFactory.cc
 src/TorrentRequestInfo.cc
 src/TorrentRequestInfo.cc
 src/UrlRequestInfo.cc
 src/UrlRequestInfo.cc
 src/main.cc
 src/main.cc
+src/version_usage.cc
 src/DefaultPieceStorage.cc
 src/DefaultPieceStorage.cc
 src/DefaultBtAnnounce.cc
 src/DefaultBtAnnounce.cc
 src/DefaultBtProgressInfoFile.cc
 src/DefaultBtProgressInfoFile.cc

+ 176 - 24
src/AbstractCommand.cc

@@ -33,44 +33,64 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "AbstractCommand.h"
 #include "AbstractCommand.h"
+#include "SegmentMan.h"
+#include "NameResolver.h"
+#include "CUIDCounter.h"
 #include "DlAbortEx.h"
 #include "DlAbortEx.h"
 #include "DlRetryEx.h"
 #include "DlRetryEx.h"
+#include "FatalException.h"
 #include "InitiateConnectionCommandFactory.h"
 #include "InitiateConnectionCommandFactory.h"
 #include "Util.h"
 #include "Util.h"
 #include "message.h"
 #include "message.h"
 #include "SleepCommand.h"
 #include "SleepCommand.h"
 #include "prefs.h"
 #include "prefs.h"
 #include "DNSCache.h"
 #include "DNSCache.h"
-#include "FatalException.h"
+#include "SingleFileDownloadContext.h"
+#include "DefaultPieceStorage.h"
+#include "UnknownLengthPieceStorage.h"
+#include "File.h"
+#include "StreamCheckIntegrityEntry.h"
+#include "DefaultBtProgressInfoFile.h"
+#include "CheckIntegrityCommand.h"
+#include "DiskAdaptor.h"
+#include "PeerStat.h"
+#include "Segment.h"
+#include "DiskWriterFactory.h"
+#include "Option.h"
 
 
 AbstractCommand::AbstractCommand(int32_t cuid,
 AbstractCommand::AbstractCommand(int32_t cuid,
 				 const RequestHandle& req,
 				 const RequestHandle& req,
 				 RequestGroup* requestGroup,
 				 RequestGroup* requestGroup,
 				 DownloadEngine* e,
 				 DownloadEngine* e,
 				 const SocketHandle& s):
 				 const SocketHandle& s):
-  Command(cuid), req(req), _requestGroup(requestGroup), e(e), socket(s),
+  Command(cuid), RequestGroupAware(requestGroup),
+  req(req), e(e), socket(s),
+  segment(0),
   checkSocketIsReadable(false), checkSocketIsWritable(false),
   checkSocketIsReadable(false), checkSocketIsWritable(false),
-  nameResolverCheck(false) {
-  
+  nameResolverCheck(false)
+{ 
   setReadCheckSocket(socket);
   setReadCheckSocket(socket);
   timeout = this->e->option->getAsInt(PREF_TIMEOUT);
   timeout = this->e->option->getAsInt(PREF_TIMEOUT);
-  ++_requestGroup->numConnection;
+  _requestGroup->increaseStreamConnection();
 }
 }
 
 
 AbstractCommand::~AbstractCommand() {
 AbstractCommand::~AbstractCommand() {
   disableReadCheckSocket();
   disableReadCheckSocket();
   disableWriteCheckSocket();
   disableWriteCheckSocket();
-  --_requestGroup->numConnection;
+  _requestGroup->decreaseStreamConnection();
 }
 }
 
 
 bool AbstractCommand::execute() {
 bool AbstractCommand::execute() {
   try {
   try {
-    if(_requestGroup->getSegmentMan()->finished()) {
+    if(_requestGroup->downloadFinished() || _requestGroup->isHaltRequested()) {
       //logger->debug("CUID#%d - finished.", cuid);
       //logger->debug("CUID#%d - finished.", cuid);
       return true;
       return true;
     }
     }
-    PeerStatHandle peerStat = _requestGroup->getSegmentMan()->getPeerStat(cuid);
-    if(peerStat.get()) {
+    PeerStatHandle peerStat = 0;
+    if(!_requestGroup->getSegmentMan().isNull()) {
+      peerStat = _requestGroup->getSegmentMan()->getPeerStat(cuid);
+    }
+    if(!peerStat.isNull()) {
       if(peerStat->getStatus() == PeerStat::REQUEST_IDLE) {
       if(peerStat->getStatus() == PeerStat::REQUEST_IDLE) {
 	logger->info(MSG_ABORT_REQUESTED, cuid);
 	logger->info(MSG_ABORT_REQUESTED, cuid);
 	onAbort(0);
 	onAbort(0);
@@ -86,9 +106,8 @@ bool AbstractCommand::execute() {
 #endif // ENABLE_ASYNC_DNS
 #endif // ENABLE_ASYNC_DNS
        !checkSocketIsReadable && !checkSocketIsWritable && !nameResolverCheck) {
        !checkSocketIsReadable && !checkSocketIsWritable && !nameResolverCheck) {
       checkPoint.reset();
       checkPoint.reset();
-      if(_requestGroup->getSegmentMan()->downloadStarted) {
-	// TODO Segment::isNull(), Change method name, it is very confusing.
-	if(segment->isNull()) {
+      if(!_requestGroup->getPieceStorage().isNull()) {
+	if(segment.isNull()) {
 	  segment = _requestGroup->getSegmentMan()->getSegment(cuid);
 	  segment = _requestGroup->getSegmentMan()->getSegment(cuid);
 	  if(segment.isNull()) {
 	  if(segment.isNull()) {
 	    logger->info(MSG_NO_SEGMENT_AVAILABLE, cuid);
 	    logger->info(MSG_NO_SEGMENT_AVAILABLE, cuid);
@@ -98,26 +117,17 @@ bool AbstractCommand::execute() {
       }
       }
       return executeInternal();
       return executeInternal();
     } else {
     } else {
-
       if(checkPoint.elapsed(timeout)) {
       if(checkPoint.elapsed(timeout)) {
 	throw new DlRetryEx(EX_TIME_OUT);
 	throw new DlRetryEx(EX_TIME_OUT);
       }
       }
       e->commands.push_back(this);
       e->commands.push_back(this);
       return false;
       return false;
     }
     }
-  } catch(FatalException* err) {
-    logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
-    onAbort(err);
-    delete(err);
-    req->resetUrl();
-    _requestGroup->getSegmentMan()->errors++;
-    return true;    
   } catch(DlAbortEx* err) {
   } catch(DlAbortEx* err) {
     logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
     logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
     onAbort(err);
     onAbort(err);
     delete(err);
     delete(err);
     req->resetUrl();
     req->resetUrl();
-    _requestGroup->getSegmentMan()->errors++;
     tryReserved();
     tryReserved();
     return true;
     return true;
   } catch(DlRetryEx* err) {
   } catch(DlRetryEx* err) {
@@ -132,13 +142,16 @@ bool AbstractCommand::execute() {
       logger->info(MSG_MAX_TRY, cuid, req->getTryCount());
       logger->info(MSG_MAX_TRY, cuid, req->getTryCount());
       logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
       logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
       delete(err);
       delete(err);
-      _requestGroup->getSegmentMan()->errors++;
       tryReserved();
       tryReserved();
       return true;
       return true;
     } else {
     } else {
       delete(err);
       delete(err);
       return prepareForRetry(e->option->getAsInt(PREF_RETRY_WAIT));
       return prepareForRetry(e->option->getAsInt(PREF_RETRY_WAIT));
     }
     }
+  } catch(FatalException* err) {
+    delete(err);
+    _requestGroup->setHaltRequested(true);
+    return true;
   }
   }
 }
 }
 
 
@@ -148,7 +161,9 @@ void AbstractCommand::tryReserved() {
 }
 }
 
 
 bool AbstractCommand::prepareForRetry(int32_t wait) {
 bool AbstractCommand::prepareForRetry(int32_t wait) {
-  _requestGroup->getSegmentMan()->cancelSegment(cuid);
+  if(!_requestGroup->getPieceStorage().isNull()) {
+    _requestGroup->getSegmentMan()->cancelSegment(cuid);
+  }
   Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, req, _requestGroup, e);
   Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, req, _requestGroup, e);
   if(wait == 0) {
   if(wait == 0) {
     e->commands.push_back(command);
     e->commands.push_back(command);
@@ -162,7 +177,9 @@ bool AbstractCommand::prepareForRetry(int32_t wait) {
 void AbstractCommand::onAbort(Exception* ex) {
 void AbstractCommand::onAbort(Exception* ex) {
   logger->debug(MSG_UNREGISTER_CUID, cuid);
   logger->debug(MSG_UNREGISTER_CUID, cuid);
   //_segmentMan->unregisterId(cuid);
   //_segmentMan->unregisterId(cuid);
-  _requestGroup->getSegmentMan()->cancelSegment(cuid);
+  if(!_requestGroup->getPieceStorage().isNull()) {
+    _requestGroup->getSegmentMan()->cancelSegment(cuid);
+  }
 }
 }
 
 
 void AbstractCommand::disableReadCheckSocket() {
 void AbstractCommand::disableReadCheckSocket() {
@@ -272,3 +289,138 @@ bool AbstractCommand::nameResolveFinished() const {
   return false;
   return false;
 }
 }
 #endif // ENABLE_ASYNC_DNS
 #endif // ENABLE_ASYNC_DNS
+
+void AbstractCommand::loadAndOpenFile()
+{
+  if(!_requestGroup->isPreLocalFileCheckEnabled()) {
+    _requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
+    return;
+  }
+
+  //_requestGroup->setProgressInfoFile(new DefaultBtProgressInfoFile(_requestGroup->getDownloadContext(), _requestGroup->getPieceStorage(), e->option));
+  BtProgressInfoFileHandle progressInfoFile =
+    new DefaultBtProgressInfoFile(_requestGroup->getDownloadContext(), _requestGroup->getPieceStorage(), e->option);
+  if(progressInfoFile->exists()) {
+    progressInfoFile->load();
+    _requestGroup->getPieceStorage()->getDiskAdaptor()->openExistingFile();
+  } else {
+    File outfile(_requestGroup->getFilePath());    
+    if(outfile.exists() && e->option->get(PREF_CONTINUE) == V_TRUE) {
+      if(_requestGroup->getTotalLength() < outfile.size()) {
+	throw new FatalException(EX_FILE_LENGTH_MISMATCH_BETWEEN_LOCAL_AND_REMOTE,
+				 _requestGroup->getFilePath().c_str(),
+				 Util::llitos(outfile.size()).c_str(),
+				 Util::llitos(_requestGroup->getTotalLength()).c_str());
+      }
+      _requestGroup->getPieceStorage()->getDiskAdaptor()->openExistingFile();
+      _requestGroup->getPieceStorage()->markPiecesDone(outfile.size());
+    } else {
+#ifdef ENABLE_MESSAGE_DIGEST
+      if(outfile.exists() && e->option->get(PREF_CHECK_INTEGRITY) == V_TRUE) {
+	_requestGroup->getPieceStorage()->getDiskAdaptor()->openExistingFile();
+      } else {
+	shouldCancelDownloadForSafety();
+	_requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
+      }
+#else // ENABLE_MESSAGE_DIGEST
+      shouldCancelDownloadForSafety();
+      _requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
+#endif // ENABLE_MESSAGE_DIGEST
+    }
+  }
+  _requestGroup->setProgressInfoFile(progressInfoFile);
+}
+
+void AbstractCommand::shouldCancelDownloadForSafety()
+{
+  File outfile(_requestGroup->getFilePath());
+  if(outfile.exists() && !_requestGroup->getProgressInfoFile()->exists()) {
+    if(e->option->get(PREF_AUTO_FILE_RENAMING) == V_TRUE) {
+      if(tryAutoFileRenaming()) {
+	logger->notice("File already exists. Renamed to %s.",
+		       _requestGroup->getFilePath().c_str());
+      } else {
+	logger->notice("File renaming failed: %s",
+		       _requestGroup->getFilePath().c_str());
+	throw new FatalException(EX_DOWNLOAD_ABORTED);
+      }
+    } else if(e->option->get(PREF_ALLOW_OVERWRITE) != V_TRUE) {
+      logger->notice(MSG_FILE_ALREADY_EXISTS,
+		     _requestGroup->getFilePath().c_str(),
+		     _requestGroup->getProgressInfoFile()->getFilename().c_str());
+      throw new FatalException(EX_DOWNLOAD_ABORTED);
+    }
+  }
+}
+
+bool AbstractCommand::tryAutoFileRenaming()
+{
+  string filepath = _requestGroup->getFilePath();
+  if(filepath.empty()) {
+    return false;
+  }
+  for(int32_t i = 1; i < 10000; ++i) {
+    File newfile(filepath+"."+Util::itos(i));
+    if(!newfile.exists()) {
+      SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setUFilename(newfile.getBasename());
+      return true;
+    }
+  }
+  return false;
+}
+
+void AbstractCommand::initPieceStorage()
+{
+  if(_requestGroup->getDownloadContext()->getTotalLength() == 0) {
+    UnknownLengthPieceStorageHandle ps = new UnknownLengthPieceStorage(_requestGroup->getDownloadContext(), e->option);
+    if(!_requestGroup->getDiskWriterFactory().isNull()) {
+      ps->setDiskWriterFactory(_requestGroup->getDiskWriterFactory());
+    }
+    _requestGroup->setPieceStorage(ps);
+  } else {
+    DefaultPieceStorageHandle ps = new DefaultPieceStorage(_requestGroup->getDownloadContext(), e->option);
+    if(!_requestGroup->getDiskWriterFactory().isNull()) {
+      ps->setDiskWriterFactory(_requestGroup->getDiskWriterFactory());
+    }
+    _requestGroup->setPieceStorage(ps);
+  }
+  _requestGroup->getPieceStorage()->initStorage();
+  _requestGroup->initSegmentMan();
+}
+
+bool AbstractCommand::downloadFinishedByFileLength()
+{
+  // check existence of control file using ProgressInfoFile class.
+  if(_requestGroup->getProgressInfoFile()->exists()) {
+    return false;
+  }
+  // TODO consider the case when the getFilePath() returns dir path. 
+  File outfile(_requestGroup->getFilePath());
+  if(outfile.exists() &&
+     _requestGroup->getTotalLength() == outfile.size()) {
+    _requestGroup->getPieceStorage()->markAllPiecesDone();
+    return true;
+  } else {
+    return false;
+  }
+}
+
+void AbstractCommand::prepareForNextAction(Command* nextCommand)
+{
+  CheckIntegrityEntryHandle entry =
+    new StreamCheckIntegrityEntry(req, _requestGroup, nextCommand);
+#ifdef ENABLE_MESSAGE_DIGEST
+  if(File(_requestGroup->getFilePath()).size() > 0 &&
+     e->option->get(PREF_CHECK_INTEGRITY) == V_TRUE &&
+     entry->isValidationReady()) {
+    entry->initValidator();
+    logger->debug("Issuing CheckIntegrityCommand.");
+    CheckIntegrityCommand* command =
+      new CheckIntegrityCommand(CUIDCounterSingletonHolder::instance()->newID(), _requestGroup, e, entry);
+    e->commands.push_back(command);
+  } else
+#endif // ENABLE_MESSAGE_DIGEST
+    {
+      e->addCommand(entry->prepareForNextAction(e));
+    }
+}

+ 25 - 7
src/AbstractCommand.h

@@ -36,20 +36,24 @@
 #define _D_ABSTRACT_COMMAND_H_
 #define _D_ABSTRACT_COMMAND_H_
 
 
 #include "Command.h"
 #include "Command.h"
-#include "Request.h"
-#include "DownloadEngine.h"
-#include "SegmentMan.h"
 #include "TimeA2.h"
 #include "TimeA2.h"
-#include "RecoverableException.h"
-#include "RequestGroup.h"
+#include "RequestGroupAware.h"
+#include "Socket.h"
 
 
-class AbstractCommand : public Command {
+class Request;
+extern typedef SharedHandle<Request> RequestHandle;
+class DownloadEngine;
+class Segment;
+extern typedef SharedHandle<Segment> SegmentHandle;
+class NameResolver;
+extern typedef SharedHandle<NameResolver> NameResolverHandle;
+
+class AbstractCommand : public Command, public RequestGroupAware {
 private:
 private:
   Time checkPoint;
   Time checkPoint;
   int32_t timeout;
   int32_t timeout;
 protected:
 protected:
   RequestHandle req;
   RequestHandle req;
-  RequestGroup* _requestGroup;
   DownloadEngine* e;
   DownloadEngine* e;
   SocketHandle socket;
   SocketHandle socket;
   SegmentHandle segment;
   SegmentHandle segment;
@@ -70,12 +74,26 @@ protected:
   virtual bool nameResolveFinished() const;
   virtual bool nameResolveFinished() const;
 #endif // ENABLE_ASYNC_DNS
 #endif // ENABLE_ASYNC_DNS
   void setTimeout(int32_t timeout) { this->timeout = timeout; }
   void setTimeout(int32_t timeout) { this->timeout = timeout; }
+
+  void loadAndOpenFile();
+
+  bool tryAutoFileRenaming();
+
+  void initPieceStorage();
+
+  bool downloadFinishedByFileLength();
+
+  void prepareForNextAction(Command* nextCommand = 0);
+
+  void shouldCancelDownloadForSafety();
+
 private:
 private:
   bool checkSocketIsReadable;
   bool checkSocketIsReadable;
   bool checkSocketIsWritable;
   bool checkSocketIsWritable;
   SocketHandle readCheckTarget;
   SocketHandle readCheckTarget;
   SocketHandle writeCheckTarget;
   SocketHandle writeCheckTarget;
   bool nameResolverCheck;
   bool nameResolverCheck;
+
 public:
 public:
   AbstractCommand(int32_t cuid, const RequestHandle& req, RequestGroup* requestGroup, DownloadEngine* e, const SocketHandle& s = SocketHandle());
   AbstractCommand(int32_t cuid, const RequestHandle& req, RequestGroup* requestGroup, DownloadEngine* e, const SocketHandle& s = SocketHandle());
   virtual ~AbstractCommand();
   virtual ~AbstractCommand();

+ 33 - 20
src/AbstractDiskWriter.cc

@@ -33,7 +33,6 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "AbstractDiskWriter.h"
 #include "AbstractDiskWriter.h"
-#include "DlAbortEx.h"
 #include "File.h"
 #include "File.h"
 #include "Util.h"
 #include "Util.h"
 #include "message.h"
 #include "message.h"
@@ -47,8 +46,6 @@
 
 
 AbstractDiskWriter::AbstractDiskWriter():
 AbstractDiskWriter::AbstractDiskWriter():
   fd(-1),
   fd(-1),
-  fileAllocator(0),
-  glowFileAllocator(0),
   logger(LogFactory::getInstance())
   logger(LogFactory::getInstance())
 {}
 {}
 
 
@@ -57,7 +54,9 @@ AbstractDiskWriter::~AbstractDiskWriter()
   closeFile();
   closeFile();
 }
 }
 
 
-void AbstractDiskWriter::openFile(const string& filename, int64_t totalLength) {
+void AbstractDiskWriter::openFile(const string& filename, int64_t totalLength)
+  throw(DlAbortEx*)
+{
   File f(filename);
   File f(filename);
   if(f.exists()) {
   if(f.exists()) {
     openExistingFile(filename, totalLength);
     openExistingFile(filename, totalLength);
@@ -66,14 +65,18 @@ void AbstractDiskWriter::openFile(const string& filename, int64_t totalLength) {
   }
   }
 }
 }
 
 
-void AbstractDiskWriter::closeFile() {
+void AbstractDiskWriter::closeFile()
+{
   if(fd >= 0) {
   if(fd >= 0) {
     close(fd);
     close(fd);
     fd = -1;
     fd = -1;
   }
   }
 }
 }
 
 
-void AbstractDiskWriter::openExistingFile(const string& filename, int64_t totalLength) {
+void AbstractDiskWriter::openExistingFile(const string& filename,
+					  int64_t totalLength)
+  throw(DlAbortEx*)
+{
   this->filename = filename;
   this->filename = filename;
   File f(filename);
   File f(filename);
   if(!f.isFile()) {
   if(!f.isFile()) {
@@ -83,17 +86,11 @@ void AbstractDiskWriter::openExistingFile(const string& filename, int64_t totalL
   if((fd = open(filename.c_str(), O_RDWR|O_BINARY, OPEN_MODE)) < 0) {
   if((fd = open(filename.c_str(), O_RDWR|O_BINARY, OPEN_MODE)) < 0) {
     throw new DlAbortEx(EX_FILE_OPEN, filename.c_str(), strerror(errno));
     throw new DlAbortEx(EX_FILE_OPEN, filename.c_str(), strerror(errno));
   }
   }
-  if(f.size() < totalLength) {
-    if(!fileAllocator.isNull()) {
-      logger->notice(MSG_ALLOCATING_FILE,
-		     filename.c_str(),
-		     Util::ullitos(totalLength).c_str());
-      glowFileAllocator->allocate(fd, totalLength);
-    }
-  }
 }
 }
 
 
-void AbstractDiskWriter::createFile(const string& filename, int32_t addFlags) {
+void AbstractDiskWriter::createFile(const string& filename, int32_t addFlags)
+  throw(DlAbortEx*)
+{
   this->filename = filename;
   this->filename = filename;
   // TODO proper filename handling needed
   // TODO proper filename handling needed
   assert(filename.size());
   assert(filename.size());
@@ -105,28 +102,36 @@ void AbstractDiskWriter::createFile(const string& filename, int32_t addFlags) {
   }  
   }  
 }
 }
 
 
-int32_t AbstractDiskWriter::writeDataInternal(const char* data, int32_t len) {
+int32_t AbstractDiskWriter::writeDataInternal(const unsigned char* data, int32_t len)
+{
   return write(fd, data, len);
   return write(fd, data, len);
 }
 }
 
 
-int32_t AbstractDiskWriter::readDataInternal(char* data, int32_t len) {
+int32_t AbstractDiskWriter::readDataInternal(unsigned char* data, int32_t len)
+{
   return read(fd, data, len);
   return read(fd, data, len);
 }
 }
 
 
-void AbstractDiskWriter::seek(int64_t offset) {
+void AbstractDiskWriter::seek(int64_t offset)
+  throw(DlAbortEx*)
+{
   if(offset != lseek(fd, offset, SEEK_SET)) {
   if(offset != lseek(fd, offset, SEEK_SET)) {
     throw new DlAbortEx(EX_FILE_SEEK, filename.c_str(), strerror(errno));
     throw new DlAbortEx(EX_FILE_SEEK, filename.c_str(), strerror(errno));
   }
   }
 }
 }
 
 
-void AbstractDiskWriter::writeData(const char* data, int32_t len, int64_t offset) {
+void AbstractDiskWriter::writeData(const unsigned char* data, int32_t len, int64_t offset)
+  throw(DlAbortEx*)
+{
   seek(offset);
   seek(offset);
   if(writeDataInternal(data, len) < 0) {
   if(writeDataInternal(data, len) < 0) {
     throw new DlAbortEx(EX_FILE_WRITE, filename.c_str(), strerror(errno));
     throw new DlAbortEx(EX_FILE_WRITE, filename.c_str(), strerror(errno));
   }
   }
 }
 }
 
 
-int32_t AbstractDiskWriter::readData(char* data, int32_t len, int64_t offset) {
+int32_t AbstractDiskWriter::readData(unsigned char* data, int32_t len, int64_t offset)
+  throw(DlAbortEx*)
+{
   int32_t ret;
   int32_t ret;
   seek(offset);
   seek(offset);
   if((ret = readDataInternal(data, len)) < 0) {
   if((ret = readDataInternal(data, len)) < 0) {
@@ -136,13 +141,21 @@ int32_t AbstractDiskWriter::readData(char* data, int32_t len, int64_t offset) {
 }
 }
 
 
 void AbstractDiskWriter::truncate(int64_t length)
 void AbstractDiskWriter::truncate(int64_t length)
+  throw(DlAbortEx*)
 {
 {
+  if(fd == -1) {
+    throw new DlAbortEx("File not opened.");
+  }
   ftruncate(fd, length);
   ftruncate(fd, length);
 }
 }
 
 
 // TODO the file descriptor fd must be opened before calling this function.
 // TODO the file descriptor fd must be opened before calling this function.
 int64_t AbstractDiskWriter::size() const
 int64_t AbstractDiskWriter::size() const
+  throw(DlAbortEx*)
 {
 {
+  if(fd == -1) {
+    throw new DlAbortEx("File not opened.");
+  }
   struct stat fileStat;
   struct stat fileStat;
   if(fstat(fd, &fileStat) < 0) {
   if(fstat(fd, &fileStat) < 0) {
     return 0;
     return 0;

+ 11 - 23
src/AbstractDiskWriter.h

@@ -36,52 +36,40 @@
 #define _D_ABSTRACT_DISK_WRITER_H_
 #define _D_ABSTRACT_DISK_WRITER_H_
 
 
 #include "DiskWriter.h"
 #include "DiskWriter.h"
-#include "FileAllocator.h"
 #include "Logger.h"
 #include "Logger.h"
+#include "DlAbortEx.h"
 
 
 class AbstractDiskWriter : public DiskWriter {
 class AbstractDiskWriter : public DiskWriter {
 protected:
 protected:
   string filename;
   string filename;
   int32_t fd;
   int32_t fd;
-  FileAllocatorHandle fileAllocator;
-  FileAllocatorHandle glowFileAllocator;
   const Logger* logger;
   const Logger* logger;
 
 
-  void createFile(const string& filename, int32_t addFlags = 0);
+  void createFile(const string& filename, int32_t addFlags = 0) throw(DlAbortEx*);
 
 
 private:
 private:
-  int32_t writeDataInternal(const char* data, int32_t len);
-  int32_t readDataInternal(char* data, int32_t len);
+  int32_t writeDataInternal(const unsigned char* data, int32_t len);
+  int32_t readDataInternal(unsigned char* data, int32_t len);
 
 
-  void seek(int64_t offset);
+  void seek(int64_t offset) throw(DlAbortEx*);
 
 
 public:
 public:
   AbstractDiskWriter();
   AbstractDiskWriter();
   virtual ~AbstractDiskWriter();
   virtual ~AbstractDiskWriter();
 
 
-  virtual void openFile(const string& filename, int64_t totalLength = 0);
+  virtual void openFile(const string& filename, int64_t totalLength = 0) throw(DlAbortEx*);
 
 
   virtual void closeFile();
   virtual void closeFile();
 
 
-  virtual void openExistingFile(const string& filename, int64_t totalLength = 0);
+  virtual void openExistingFile(const string& filename, int64_t totalLength = 0) throw(DlAbortEx*);
 
 
-  virtual void writeData(const char* data, int32_t len, int64_t offset);
+  virtual void writeData(const unsigned char* data, int32_t len, int64_t offset) throw(DlAbortEx*);
 
 
-  virtual int32_t readData(char* data, int32_t len, int64_t offset);
+  virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) throw(DlAbortEx*);
 
 
-  void setFileAllocator(const FileAllocatorHandle& fileAllocator)
-  {
-    this->fileAllocator = fileAllocator;
-  }
+  virtual void truncate(int64_t length) throw(DlAbortEx*);
 
 
-  void setGlowFileAllocator(const FileAllocatorHandle& fileAllocator)
-  {
-    this->glowFileAllocator = fileAllocator;
-  }
-
-  virtual void truncate(int64_t length);
-
-  virtual int64_t size() const;
+  virtual int64_t size() const throw(DlAbortEx*);
 };
 };
 
 
 #endif // _D_ABSTRACT_DISK_WRITER_H_
 #endif // _D_ABSTRACT_DISK_WRITER_H_

+ 3 - 0
src/AbstractProxyRequestCommand.cc

@@ -33,6 +33,9 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "AbstractProxyRequestCommand.h"
 #include "AbstractProxyRequestCommand.h"
+#include "DownloadEngine.h"
+#include "RequestGroup.h"
+#include "Request.h"
 #include "HttpConnection.h"
 #include "HttpConnection.h"
 #include "prefs.h"
 #include "prefs.h"
 
 

+ 3 - 1
src/AbstractProxyRequestCommand.h

@@ -36,7 +36,9 @@
 #define _D_ABSTRACT_PROXY_REQUEST_COMMAND_H_
 #define _D_ABSTRACT_PROXY_REQUEST_COMMAND_H_
 
 
 #include "AbstractCommand.h"
 #include "AbstractCommand.h"
-#include "HttpConnection.h"
+
+class HttpConnection;
+extern typedef SharedHandle<HttpConnection> HttpConnectionHandle;
 
 
 class AbstractProxyRequestCommand : public AbstractCommand {
 class AbstractProxyRequestCommand : public AbstractCommand {
 protected:
 protected:

+ 5 - 0
src/AbstractProxyResponseCommand.cc

@@ -33,6 +33,11 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "AbstractProxyResponseCommand.h"
 #include "AbstractProxyResponseCommand.h"
+#include "HttpConnection.h"
+#include "Request.h"
+#include "RequestGroup.h"
+#include "DownloadEngine.h"
+#include "HttpResponse.h"
 #include "HttpRequestCommand.h"
 #include "HttpRequestCommand.h"
 #include "DlRetryEx.h"
 #include "DlRetryEx.h"
 #include "message.h"
 #include "message.h"

+ 3 - 1
src/AbstractProxyResponseCommand.h

@@ -36,7 +36,9 @@
 #define _D_ABSTRACT_PROXY_RESPONSE_COMMAND_H_
 #define _D_ABSTRACT_PROXY_RESPONSE_COMMAND_H_
 
 
 #include "AbstractCommand.h"
 #include "AbstractCommand.h"
-#include "HttpConnection.h"
+
+class HttpConnection;
+extern typedef SharedHandle<HttpConnection> HttpConnectionHandle;
 
 
 class AbstractProxyResponseCommand : public AbstractCommand {
 class AbstractProxyResponseCommand : public AbstractCommand {
 protected:
 protected:

+ 23 - 6
src/AbstractSingleDiskAdaptor.cc

@@ -34,28 +34,40 @@
 /* copyright --> */
 /* copyright --> */
 #include "AbstractSingleDiskAdaptor.h"
 #include "AbstractSingleDiskAdaptor.h"
 #include "File.h"
 #include "File.h"
+#include "SingleFileAllocationIterator.h"
 
 
-void AbstractSingleDiskAdaptor::initAndOpenFile() {
+void AbstractSingleDiskAdaptor::initAndOpenFile()
+  throw(DlAbortEx*)
+{
   diskWriter->initAndOpenFile(getFilePath(), totalLength);
   diskWriter->initAndOpenFile(getFilePath(), totalLength);
 }
 }
 
 
-void AbstractSingleDiskAdaptor::openFile() {
+void AbstractSingleDiskAdaptor::openFile()
+  throw(DlAbortEx*)
+{
   diskWriter->openFile(getFilePath(), totalLength);
   diskWriter->openFile(getFilePath(), totalLength);
 }
 }
 
 
-void AbstractSingleDiskAdaptor::closeFile() {
+void AbstractSingleDiskAdaptor::closeFile()
+{
   diskWriter->closeFile();
   diskWriter->closeFile();
 }
 }
 
 
-void AbstractSingleDiskAdaptor::openExistingFile() {
+void AbstractSingleDiskAdaptor::openExistingFile()
+  throw(DlAbortEx*)
+{
   diskWriter->openExistingFile(getFilePath(), totalLength);
   diskWriter->openExistingFile(getFilePath(), totalLength);
 }
 }
 
 
-void AbstractSingleDiskAdaptor::writeData(const unsigned char* data, int32_t len, int64_t offset) {
+void AbstractSingleDiskAdaptor::writeData(const unsigned char* data, int32_t len, int64_t offset)
+  throw(DlAbortEx*)
+{
   diskWriter->writeData(data, len, offset);
   diskWriter->writeData(data, len, offset);
 }
 }
 
 
-int32_t AbstractSingleDiskAdaptor::readData(unsigned char* data, int32_t len, int64_t offset) {
+int32_t AbstractSingleDiskAdaptor::readData(unsigned char* data, int32_t len, int64_t offset)
+  throw(DlAbortEx*)
+{
   return diskWriter->readData(data, len, offset);
   return diskWriter->readData(data, len, offset);
 }
 }
 
 
@@ -63,3 +75,8 @@ bool AbstractSingleDiskAdaptor::fileExists()
 {
 {
   return File(getFilePath()).exists();
   return File(getFilePath()).exists();
 }
 }
+
+FileAllocationIteratorHandle AbstractSingleDiskAdaptor::fileAllocationIterator()
+{
+  return new SingleFileAllocationIterator(this);
+}

+ 16 - 8
src/AbstractSingleDiskAdaptor.h

@@ -37,6 +37,7 @@
 
 
 #include "DiskAdaptor.h"
 #include "DiskAdaptor.h"
 #include "DiskWriter.h"
 #include "DiskWriter.h"
+#include "DlAbortEx.h"
 
 
 class AbstractSingleDiskAdaptor : public DiskAdaptor {
 class AbstractSingleDiskAdaptor : public DiskAdaptor {
 protected:
 protected:
@@ -47,26 +48,33 @@ public:
 
 
   virtual ~AbstractSingleDiskAdaptor() {}
   virtual ~AbstractSingleDiskAdaptor() {}
 
 
-  virtual void initAndOpenFile();
+  virtual void initAndOpenFile() throw(DlAbortEx*);
 
 
-  virtual void openFile();
+  virtual void openFile() throw(DlAbortEx*);
 
 
   virtual void closeFile();
   virtual void closeFile();
 
 
-  virtual void openExistingFile();
+  virtual void openExistingFile() throw(DlAbortEx*);
 
 
   virtual void writeData(const unsigned char* data, int32_t len,
   virtual void writeData(const unsigned char* data, int32_t len,
-			 int64_t offset);
+			 int64_t offset) throw(DlAbortEx*);
 
 
-  virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset);
+  virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) throw(DlAbortEx*);
 
 
   virtual bool fileExists();
   virtual bool fileExists();
 
 
-  virtual int64_t size() const
+  virtual int64_t size() const throw(DlAbortEx*)
   {
   {
-    return getTotalLength();
+    return diskWriter->size();
   }
   }
-    
+
+  virtual void truncate(int64_t length) throw(DlAbortEx*)
+  {
+    diskWriter->truncate(length);
+  }
+  
+  virtual FileAllocationIteratorHandle fileAllocationIterator();
+
   void setDiskWriter(const DiskWriterHandle diskWriter) {
   void setDiskWriter(const DiskWriterHandle diskWriter) {
     this->diskWriter = diskWriter;
     this->diskWriter = diskWriter;
   }
   }

+ 17 - 1
src/ActivePeerConnectionCommand.cc

@@ -37,6 +37,22 @@
 #include "CUIDCounter.h"
 #include "CUIDCounter.h"
 #include "message.h"
 #include "message.h"
 
 
+ActivePeerConnectionCommand::ActivePeerConnectionCommand(int cuid,
+							 RequestGroup* requestGroup,
+							 DownloadEngine* e,
+							 const BtContextHandle& btContext,
+							 int32_t interval)
+  :Command(cuid),
+   BtContextAwareCommand(btContext),
+   RequestGroupAware(requestGroup),
+   interval(interval),
+   e(e),
+   _lowestSpeedLimit(20*1024),
+   _numNewConnection(5)
+{}
+
+ActivePeerConnectionCommand::~ActivePeerConnectionCommand() {}
+
 bool ActivePeerConnectionCommand::execute() {
 bool ActivePeerConnectionCommand::execute() {
   if(btRuntime->isHalt()) {
   if(btRuntime->isHalt()) {
     return true;
     return true;
@@ -63,7 +79,7 @@ void ActivePeerConnectionCommand::connectToPeer(const PeerHandle& peer)
   }
   }
   peer->cuid = CUIDCounterSingletonHolder::instance()->newID();
   peer->cuid = CUIDCounterSingletonHolder::instance()->newID();
   PeerInitiateConnectionCommand* command =
   PeerInitiateConnectionCommand* command =
-    new PeerInitiateConnectionCommand(peer->cuid, peer, e, btContext);
+    new PeerInitiateConnectionCommand(peer->cuid, _requestGroup, peer, e, btContext);
   e->commands.push_back(command);
   e->commands.push_back(command);
   logger->info(MSG_CONNECTING_TO_PEER,
   logger->info(MSG_CONNECTING_TO_PEER,
 	       cuid, peer->ipaddr.c_str());
 	       cuid, peer->ipaddr.c_str());

+ 12 - 12
src/ActivePeerConnectionCommand.h

@@ -35,30 +35,30 @@
 #ifndef _D_ACTIVE_PEER_CONNECTION_COMMAND_H_
 #ifndef _D_ACTIVE_PEER_CONNECTION_COMMAND_H_
 #define _D_ACTIVE_PEER_CONNECTION_COMMAND_H_
 #define _D_ACTIVE_PEER_CONNECTION_COMMAND_H_
 
 
+#include "Command.h"
 #include "BtContextAwareCommand.h"
 #include "BtContextAwareCommand.h"
-#include "TorrentDownloadEngine.h"
+#include "DownloadEngine.h"
 #include "TimeA2.h"
 #include "TimeA2.h"
+#include "RequestGroupAware.h"
 
 
-class ActivePeerConnectionCommand : public BtContextAwareCommand {
+class ActivePeerConnectionCommand : public Command,
+				    public BtContextAwareCommand,
+				    public RequestGroupAware
+{
 private:
 private:
   int32_t interval; // UNIT: sec
   int32_t interval; // UNIT: sec
-  TorrentDownloadEngine* e;
+  DownloadEngine* e;
   Time checkPoint;
   Time checkPoint;
   int32_t _lowestSpeedLimit; // UNIT: byte/sec
   int32_t _lowestSpeedLimit; // UNIT: byte/sec
   int32_t _numNewConnection; // the number of the connection to establish.
   int32_t _numNewConnection; // the number of the connection to establish.
 public:
 public:
   ActivePeerConnectionCommand(int cuid,
   ActivePeerConnectionCommand(int cuid,
-			      TorrentDownloadEngine* e,
+			      RequestGroup* requestGroup,
+			      DownloadEngine* e,
 			      const BtContextHandle& btContext,
 			      const BtContextHandle& btContext,
-			      int32_t interval)
-    :BtContextAwareCommand(cuid, btContext),
-     interval(interval),
-     e(e),
-    _lowestSpeedLimit(20*1024),
-    _numNewConnection(5)
-    {}
+			      int32_t interval);
      
      
-  virtual ~ActivePeerConnectionCommand() {}
+  virtual ~ActivePeerConnectionCommand();
 
 
   virtual bool execute();
   virtual bool execute();
 
 

+ 2 - 2
src/AlphaNumberDecorator.h

@@ -36,7 +36,7 @@
 #define _D_ALPHA_NUMBER_DECORATOR_H_
 #define _D_ALPHA_NUMBER_DECORATOR_H_
 
 
 #include "NumberDecorator.h"
 #include "NumberDecorator.h"
-#include "FatalException.h"
+#include "DlAbortEx.h"
 
 
 class AlphaNumberDecorator : public NumberDecorator
 class AlphaNumberDecorator : public NumberDecorator
 {
 {
@@ -64,7 +64,7 @@ public:
   virtual string decorate(int32_t number)
   virtual string decorate(int32_t number)
   {
   {
     if(number < 0) {
     if(number < 0) {
-      throw new FatalException("The number must be greater than 0.");
+      throw new DlAbortEx("The number must be greater than 0.");
     }
     }
     if(number == 0) {
     if(number == 0) {
       return widen(_zero, _width);
       return widen(_zero, _width);

+ 8 - 1
src/AutoSaveCommand.cc

@@ -33,10 +33,17 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "AutoSaveCommand.h"
 #include "AutoSaveCommand.h"
+#include "DownloadEngine.h"
+#include "RequestGroupMan.h"
+
+AutoSaveCommand::AutoSaveCommand(int32_t cuid, DownloadEngine* e, int32_t interval):
+  TimeBasedCommand(cuid, e, interval) {}
+
+AutoSaveCommand::~AutoSaveCommand() {}
 
 
 void AutoSaveCommand::preProcess()
 void AutoSaveCommand::preProcess()
 {
 {
-  if(_e->_requestGroupMan->downloadFinished()) {
+  if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
     _exit = true;
     _exit = true;
   }
   }
 }
 }

+ 2 - 3
src/AutoSaveCommand.h

@@ -40,10 +40,9 @@
 class AutoSaveCommand : public TimeBasedCommand
 class AutoSaveCommand : public TimeBasedCommand
 {
 {
 public:
 public:
-  AutoSaveCommand(int32_t cuid, DownloadEngine* e, int32_t interval):
-    TimeBasedCommand(cuid, e, interval) {}
+  AutoSaveCommand(int32_t cuid, DownloadEngine* e, int32_t interval);
 
 
-  virtual ~AutoSaveCommand() {}
+  virtual ~AutoSaveCommand();
 
 
   virtual void preProcess();
   virtual void preProcess();
 
 

+ 52 - 0
src/BinaryStream.h

@@ -0,0 +1,52 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_BINARY_STREAM_H_
+#define _D_BINARY_STREAM_H_
+
+#include "common.h"
+#include "DlAbortEx.h"
+
+class BinaryStream {
+public:
+  virtual ~BinaryStream() {}
+  
+  virtual void writeData(const unsigned char* data, int32_t len, int64_t offset) = 0;
+
+  virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) = 0;
+};
+
+typedef SharedHandle<BinaryStream> BinaryStreamHandle;
+
+#endif // _D_BINARY_STREAM_H_

+ 22 - 30
src/ConsoleDownloadEngine.h → src/BtCheckIntegrityEntry.cc

@@ -32,37 +32,29 @@
  * files in the program, then also delete it here.
  * files in the program, then also delete it here.
  */
  */
 /* copyright --> */
 /* copyright --> */
-#ifndef _D_CONSOLE_DOWNLOAD_ENGINE_H_
-#define _D_CONSOLE_DOWNLOAD_ENGINE_H_
-
+#include "BtCheckIntegrityEntry.h"
+#include "BtSetup.h"
+#include "BtFileAllocationEntry.h"
+#include "CUIDCounter.h"
+#include "RequestGroup.h"
+#include "PieceStorage.h"
 #include "DownloadEngine.h"
 #include "DownloadEngine.h"
-#include "TimeA2.h"
+#include "FileAllocationMan.h"
+#include "DiskAdaptor.h"
 
 
-class ConsoleDownloadEngine : public DownloadEngine {
-private:
-  Time cp;
-  int64_t psize;
-  int32_t speed;
-  // The time when startup
-  Time startup;
-  // The number of bytes downloaded at startup
-  int64_t startupLength;
-  bool isStartupLengthSet;
-  // The average speed(bytes per second) since startup
-  int32_t avgSpeed;
-  // The estimated remaining time to complete the download.
-  int32_t eta;
-protected:
-  void sendStatistics(int64_t currentSize, int64_t totalSize);
-  virtual void initStatistics();
-  virtual void calculateStatistics();
-  virtual void onEndOfRun();
-  virtual void afterEachIteration();
-public:
-  ConsoleDownloadEngine();
-  ~ConsoleDownloadEngine();
+BtCheckIntegrityEntry::BtCheckIntegrityEntry(RequestGroup* requestGroup):
+  CheckIntegrityEntry(requestGroup, 0) {}
 
 
-  void fillCommand();
-};
+BtCheckIntegrityEntry::~BtCheckIntegrityEntry() {}
 
 
-#endif // _D_CONSOLE_DOWNLOAD_ENGINE_H_
+Commands BtCheckIntegrityEntry::prepareForNextAction(DownloadEngine* e)
+{
+  Commands commands;
+  FileAllocationEntryHandle entry = new BtFileAllocationEntry(_requestGroup);
+  if(_requestGroup->isFileAllocationEnabled() && !_requestGroup->getPieceStorage()->getDiskAdaptor()->fileAllocationIterator()->finished()) {
+    e->_fileAllocationMan->pushFileAllocationEntry(entry);
+  } else {
+    commands = entry->prepareForNextAction(e);
+  }
+  return commands;
+}

+ 51 - 0
src/BtCheckIntegrityEntry.h

@@ -0,0 +1,51 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_BT_CHECK_INTEGRITY_ENTRY_H_
+#define _D_BT_CHECK_INTEGRITY_ENTRY_H_
+
+#include "CheckIntegrityEntry.h"
+
+class BtCheckIntegrityEntry : public CheckIntegrityEntry {
+public:
+  BtCheckIntegrityEntry(RequestGroup* requestGroup);
+
+  virtual ~BtCheckIntegrityEntry();
+
+  virtual Commands prepareForNextAction(DownloadEngine* e);
+};
+
+typedef SharedHandle<BtCheckIntegrityEntry> BtCheckIntegrityEntryHandle;
+
+#endif // _D_BT_FILE_ALLOCATION_ENTRY_H_

+ 8 - 25
src/BtContext.h

@@ -35,57 +35,40 @@
 #ifndef _D_BT_CONTEXT_H_
 #ifndef _D_BT_CONTEXT_H_
 #define _D_BT_CONTEXT_H_
 #define _D_BT_CONTEXT_H_
 
 
-#include "common.h"
-#include "FileEntry.h"
-#include "AnnounceTier.h"
+#include "DownloadContext.h"
 
 
 #define INFO_HASH_LENGTH 20
 #define INFO_HASH_LENGTH 20
 #define MAX_PEER_ERROR 5
 #define MAX_PEER_ERROR 5
 #define MAX_PEERS 55
 #define MAX_PEERS 55
 
 
+class AnnounceTier;
+extern typedef SharedHandle<AnnounceTier> AnnounceTierHandle;
 typedef deque<AnnounceTierHandle> AnnounceTiers;
 typedef deque<AnnounceTierHandle> AnnounceTiers;
 
 
-class BtContext {
+class RequestGroup;
+
+class BtContext:public DownloadContext {
 public:
 public:
   virtual ~BtContext() {}
   virtual ~BtContext() {}
 
 
-  enum FILE_MODE {
-    SINGLE,
-    MULTI
-  };
-
   virtual const unsigned char* getInfoHash() const = 0;
   virtual const unsigned char* getInfoHash() const = 0;
 
 
   virtual int32_t getInfoHashLength() const = 0;
   virtual int32_t getInfoHashLength() const = 0;
 
 
   virtual string getInfoHashAsString() const = 0;
   virtual string getInfoHashAsString() const = 0;
 
 
-  virtual string getPieceHash(int32_t index) const = 0;
-  
-  virtual const Strings& getPieceHashes() const = 0;
-
-  virtual int64_t getTotalLength() const = 0;
-
-  virtual FILE_MODE getFileMode() const = 0;
-
-  virtual FileEntries getFileEntries() const = 0;
-
   virtual AnnounceTiers getAnnounceTiers() const = 0;
   virtual AnnounceTiers getAnnounceTiers() const = 0;
 
 
   virtual void load(const string& torrentFile) = 0;
   virtual void load(const string& torrentFile) = 0;
 
 
-  virtual string getName() const = 0;
-  
-  virtual int32_t getPieceLength() const = 0;
-
-  virtual int32_t getNumPieces() const = 0;
-
   /**
   /**
    * Returns the peer id of localhost, 20 byte length
    * Returns the peer id of localhost, 20 byte length
    */
    */
   virtual const unsigned char* getPeerId() = 0;
   virtual const unsigned char* getPeerId() = 0;
 
 
   virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize) = 0;
   virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize) = 0;
+  
+  virtual RequestGroup* getOwnerRequestGroup() = 0;
 
 
 };
 };
 
 

+ 1 - 3
src/BtContextAwareCommand.cc

@@ -35,9 +35,7 @@
 #include "BtContextAwareCommand.h"
 #include "BtContextAwareCommand.h"
 #include "BtRegistry.h"
 #include "BtRegistry.h"
 
 
-BtContextAwareCommand::BtContextAwareCommand(int cuid,
-					     const BtContextHandle& btContext):
-  Command(cuid),
+BtContextAwareCommand::BtContextAwareCommand(const BtContextHandle& btContext):
   btContext(btContext),
   btContext(btContext),
   btRuntime(BT_RUNTIME(btContext)),
   btRuntime(BT_RUNTIME(btContext)),
   pieceStorage(PIECE_STORAGE(btContext)),
   pieceStorage(PIECE_STORAGE(btContext)),

+ 4 - 3
src/BtContextAwareCommand.h

@@ -35,7 +35,7 @@
 #ifndef _D_BT_CONTEXT_AWARE_COMMAND_H_
 #ifndef _D_BT_CONTEXT_AWARE_COMMAND_H_
 #define _D_BT_CONTEXT_AWARE_COMMAND_H_
 #define _D_BT_CONTEXT_AWARE_COMMAND_H_
 
 
-#include "Command.h"
+#include "common.h"
 #include "BtContext.h"
 #include "BtContext.h"
 #include "BtRuntime.h"
 #include "BtRuntime.h"
 #include "PieceStorage.h"
 #include "PieceStorage.h"
@@ -43,7 +43,8 @@
 #include "BtAnnounce.h"
 #include "BtAnnounce.h"
 #include "BtProgressInfoFile.h"
 #include "BtProgressInfoFile.h"
 
 
-class BtContextAwareCommand : public Command {
+class BtContextAwareCommand
+{
 protected:
 protected:
   BtContextHandle btContext;
   BtContextHandle btContext;
   BtRuntimeHandle btRuntime;
   BtRuntimeHandle btRuntime;
@@ -52,7 +53,7 @@ protected:
   BtAnnounceHandle btAnnounce;
   BtAnnounceHandle btAnnounce;
   BtProgressInfoFileHandle btProgressInfoFile;
   BtProgressInfoFileHandle btProgressInfoFile;
 public:
 public:
-  BtContextAwareCommand(int cuid, const BtContextHandle& btContext);
+  BtContextAwareCommand(const BtContextHandle& btContext);
 
 
   virtual ~BtContextAwareCommand();
   virtual ~BtContextAwareCommand();
 };
 };

+ 83 - 0
src/BtDependency.cc

@@ -0,0 +1,83 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "BtDependency.h"
+#include "RequestGroup.h"
+#include "Option.h"
+#include "LogFactory.h"
+#include "DefaultBtContext.h"
+#include "RecoverableException.h"
+#include "message.h"
+#include "prefs.h"
+
+BtDependency::BtDependency(const RequestGroupWeakHandle& dependant,
+			   const RequestGroupWeakHandle& dependee,
+			   const Option* option):
+  _dependant(dependant),
+  _dependee(dependee),
+  _option(option),
+  _logger(LogFactory::getInstance()) {}
+
+BtDependency::~BtDependency() {}
+
+bool BtDependency::resolve()
+{
+  if(_dependee->getNumCommand() == 0 && _dependee->downloadFinished()) {
+    DefaultBtContextHandle btContext = new DefaultBtContext();
+    try {
+      btContext->load(_dependee->getFilePath());
+      if(_option->defined(PREF_PEER_ID_PREFIX)) {
+	btContext->setPeerIdPrefix(_option->get(PREF_PEER_ID_PREFIX));
+      }
+      btContext->setDir(_dependant->getDownloadContext()->getDir());
+    } catch(RecoverableException* e) {
+      _logger->error(EX_EXCEPTION_CAUGHT, e);
+      delete e;
+      _logger->debug("BtDependency for GID#%d failed. Go without Bt.",
+		     _dependant->getGID());
+      return true;
+    }
+    _logger->debug("Dependency resolved for GID#%d", _dependant->getGID());
+    _dependant->setDownloadContext(btContext);
+    btContext->setOwnerRequestGroup(_dependant.get());
+    return true;
+  } else if(_dependee->getNumCommand() == 0) {
+    // _dependee's download failed.
+    _logger->debug("BtDependency for GID#%d failed. Go without Bt.",
+		   _dependant->getGID());    
+    return true;
+  } else {
+    return false;
+  }
+}

+ 22 - 19
src/TorrentRequestInfo.h → src/BtDependency.h

@@ -32,30 +32,33 @@
  * files in the program, then also delete it here.
  * files in the program, then also delete it here.
  */
  */
 /* copyright --> */
 /* copyright --> */
-#ifndef _D_TORRENT_REQUEST_INFO_H_
-#define _D_TORRENT_REQUEST_INFO_H_
+#ifndef _D_BT_DEPENDENCY_H_
+#define _D_BT_DEPENDENCY_H_
 
 
-#include "RequestInfo.h"
-#include "TorrentDownloadEngine.h"
-#include "BtContext.h"
+#include "Dependency.h"
 
 
-class TorrentRequestInfo : public RequestInfo {
-private:
-  string torrentFile;
-  Strings targetFiles;
+class RequestGroup;
+extern typedef WeakHandle<RequestGroup> RequestGroupWeakHandle;
+class Option;
+class Logger;
 
 
+class BtDependency : public Dependency
+{
+private:
+  RequestGroupWeakHandle _dependant;
+  RequestGroupWeakHandle _dependee;
+  const Option* _option;
+  const Logger* _logger;
 public:
 public:
-  TorrentRequestInfo(const string& torrentFile, Option* op):
-    RequestInfo(op),
-    torrentFile(torrentFile) {}
+  BtDependency(const RequestGroupWeakHandle& dependant,
+	       const RequestGroupWeakHandle& dependee,
+	       const Option* option);
 
 
-  virtual ~TorrentRequestInfo() {}
+  virtual ~BtDependency();
 
 
-  virtual RequestInfos execute();
-
-  void setTargetFiles(const Strings& targetFiles) {
-    this->targetFiles = targetFiles;
-  }
+  virtual bool resolve();
 };
 };
 
 
-#endif // _D_TORRENT_REQUEST_INFO_H_
+typedef SharedHandle<BtDependency> BtDependencyHandle;
+
+#endif // _D_BT_DEPENDENCY_H_

+ 15 - 20
src/TorrentAutoSaveCommand.cc → src/BtFileAllocationEntry.cc

@@ -32,27 +32,22 @@
  * files in the program, then also delete it here.
  * files in the program, then also delete it here.
  */
  */
 /* copyright --> */
 /* copyright --> */
-#include "TorrentAutoSaveCommand.h"
-#include "Util.h"
+#include "BtFileAllocationEntry.h"
+#include "BtSetup.h"
+#include "RequestGroup.h"
+#include "Command.h"
+#include "DownloadEngine.h"
 
 
-TorrentAutoSaveCommand::TorrentAutoSaveCommand(int32_t cuid,
-					       TorrentDownloadEngine* e,
-					       const BtContextHandle& btContext,
-					       int32_t interval):
-  BtContextAwareCommand(cuid, btContext),
-  e(e),
-  interval(interval) {}
+BtFileAllocationEntry::BtFileAllocationEntry(RequestGroup* requestGroup):
+  FileAllocationEntry(requestGroup, 0) {}
 
 
-TorrentAutoSaveCommand::~TorrentAutoSaveCommand() {}
+BtFileAllocationEntry::~BtFileAllocationEntry() {}
 
 
-bool TorrentAutoSaveCommand::execute() {
-  if(checkPoint.elapsed(interval) || btRuntime->isHalt()) {
-    checkPoint.reset();
-    btProgressInfoFile->save();
-    if(btRuntime->isHalt()) {
-      return true;
-    }
-  }
-  e->commands.push_back(this);
-  return false;
+Commands BtFileAllocationEntry::prepareForNextAction(DownloadEngine* e)
+{
+  Commands commands = BtSetup().setup(_requestGroup, e, e->option);
+  // TODO don't integerate http/ftp when multi-file torrent
+  Commands streamCommands = _requestGroup->createNextCommandWithAdj(e, 0);
+  copy(streamCommands.begin(), streamCommands.end(), back_inserter(commands));
+  return commands;
 }
 }

+ 56 - 0
src/BtFileAllocationEntry.h

@@ -0,0 +1,56 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_BT_FILE_ALLOCATION_ENTRY_H_
+#define _D_BT_FILE_ALLOCATION_ENTRY_H_
+
+#include "FileAllocationEntry.h"
+
+class RequestGroup;
+class DownloadEngine;
+class Command;
+extern typedef deque<Command*> Commands;
+
+class BtFileAllocationEntry : public FileAllocationEntry {
+public:
+  BtFileAllocationEntry(RequestGroup* requestGroup);
+
+  virtual ~BtFileAllocationEntry();
+
+  virtual Commands prepareForNextAction(DownloadEngine* e);
+};
+
+typedef SharedHandle<BtFileAllocationEntry> BtFileAllocationEntryHandle;
+
+#endif // _D_BT_FILE_ALLOCATION_ENTRY_H_

+ 2 - 2
src/BtPieceMessage.cc

@@ -39,8 +39,8 @@
 #include "DlAbortEx.h"
 #include "DlAbortEx.h"
 #include "BtChokingEvent.h"
 #include "BtChokingEvent.h"
 #include "BtCancelSendingPieceEvent.h"
 #include "BtCancelSendingPieceEvent.h"
-#include "DiskAdaptorWriter.h"
 #include "MessageDigestHelper.h"
 #include "MessageDigestHelper.h"
+#include "DiskAdaptor.h"
 
 
 void BtPieceMessage::setBlock(const unsigned char* block, int32_t blockLength) {
 void BtPieceMessage::setBlock(const unsigned char* block, int32_t blockLength) {
   delete [] this->block;
   delete [] this->block;
@@ -193,7 +193,7 @@ bool BtPieceMessage::checkPieceHash(const PieceHandle& piece) {
   int64_t offset =
   int64_t offset =
     ((int64_t)piece->getIndex())*btContext->getPieceLength();
     ((int64_t)piece->getIndex())*btContext->getPieceLength();
   
   
-  return MessageDigestHelper::digest("sha1", new DiskAdaptorWriter(pieceStorage->getDiskAdaptor()), offset, piece->getLength())
+  return MessageDigestHelper::digest("sha1", pieceStorage->getDiskAdaptor(), offset, piece->getLength())
     == btContext->getPieceHash(piece->getIndex());
     == btContext->getPieceHash(piece->getIndex());
 }
 }
 
 

+ 24 - 21
src/ConsoleFileAllocationMonitor.cc → src/BtPostDownloadHandler.cc

@@ -32,28 +32,31 @@
  * files in the program, then also delete it here.
  * files in the program, then also delete it here.
  */
  */
 /* copyright --> */
 /* copyright --> */
-#include "ConsoleFileAllocationMonitor.h"
-#include "Util.h"
+#include "BtPostDownloadHandler.h"
+#include "DefaultBtContext.h"
+#include "prefs.h"
+#include "RequestGroup.h"
+#include "Option.h"
 
 
-void ConsoleFileAllocationMonitor::showProgress() {
-  int32_t progressPercentage = (int32_t)(((current-min)*1.0/(max-min))*100);
-  int32_t numOfStar = progressPercentage/10*2;
+BtPostDownloadHandler::BtPostDownloadHandler(const Option* option):
+  PostDownloadHandler(".torrent", option)
+{}
 
 
-  cout << "\r                                                                                ";
-  cout << "\r";
-  cout << "|";
-  for(int32_t i = 0; i < numOfStar; ++i) {
-    cout << "*";
-  }
-  for(int32_t i = 0; i < 20-numOfStar; ++i) {
-    cout << " ";
+BtPostDownloadHandler::~BtPostDownloadHandler() {}
+
+RequestGroups BtPostDownloadHandler::getNextRequestGroups(const string& path)
+{
+  RequestGroupHandle rg = new RequestGroup(_option, Strings());
+  DefaultBtContextHandle btContext = new DefaultBtContext();
+  btContext->load(path);
+  if(_option->defined(PREF_PEER_ID_PREFIX)) {
+    btContext->setPeerIdPrefix(_option->get(PREF_PEER_ID_PREFIX));
   }
   }
-  cout << "|";
-  cout << progressPercentage << "%";
-  cout << "(";
-  cout << Util::ullitos(current, true) << "/" << Util::ullitos(max, true);
-  cout << ")";
-  cout << flush;
-  // Example,
-  // |******************* | 95%(1,333,3256/1,553,3232 bytes)
+  btContext->setDir(_option->get(PREF_DIR));
+  rg->setDownloadContext(btContext);
+  btContext->setOwnerRequestGroup(rg.get());
+  
+  RequestGroups groups;
+  groups.push_back(rg);
+  return groups;
 }
 }

+ 51 - 0
src/BtPostDownloadHandler.h

@@ -0,0 +1,51 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_BT_POST_DOWNLOAD_HANDLER_H_
+#define _D_BT_POST_DOWNLOAD_HANDLER_H_
+
+#include "PostDownloadHandler.h"
+
+class BtPostDownloadHandler:public PostDownloadHandler
+{
+public:
+  BtPostDownloadHandler(const Option* option);
+
+  virtual ~BtPostDownloadHandler();
+
+  virtual RequestGroups getNextRequestGroups(const string& path);
+};
+
+typedef SharedHandle<BtPostDownloadHandler> BtPostDownloadHandlerHandle;
+#endif // _D_BT_POST_DOWNLOAD_HANDLER_H_

+ 0 - 2
src/BtProgressInfoFile.h

@@ -43,8 +43,6 @@ public:
 
 
   virtual string getFilename() = 0;
   virtual string getFilename() = 0;
 
 
-  virtual void setFilename(const string& filename) = 0;
-
   virtual bool exists() = 0;
   virtual bool exists() = 0;
 
 
   virtual void save() = 0;
   virtual void save() = 0;

+ 62 - 65
src/BtRegistry.cc

@@ -35,6 +35,7 @@
 #include "BtRegistry.h"
 #include "BtRegistry.h"
 #include "DlAbortEx.h"
 #include "DlAbortEx.h"
 
 
+BtContextMap BtRegistry::btContextMap;
 PeerStorageMap BtRegistry::peerStorageMap;
 PeerStorageMap BtRegistry::peerStorageMap;
 PieceStorageMap BtRegistry::pieceStorageMap;
 PieceStorageMap BtRegistry::pieceStorageMap;
 BtAnnounceMap BtRegistry::btAnnounceMap;
 BtAnnounceMap BtRegistry::btAnnounceMap;
@@ -42,93 +43,77 @@ BtRuntimeMap BtRegistry::btRuntimeMap;
 BtProgressInfoFileMap BtRegistry::btProgressInfoFileMap;
 BtProgressInfoFileMap BtRegistry::btProgressInfoFileMap;
 PeerObjectClusterRegistry BtRegistry::peerObjectClusterRegistry;
 PeerObjectClusterRegistry BtRegistry::peerObjectClusterRegistry;
 
 
-PeerStorageHandle BtRegistry::getPeerStorage(const string& key) {
-  PeerStorageMap::iterator itr = peerStorageMap.find(key);
-  if(itr == peerStorageMap.end()) {
-    return PeerStorageHandle(0);
-  } else {
-    return itr->second;
-  }
+PeerStorageHandle BtRegistry::getPeerStorage(const string& key)
+{
+  return peerStorageMap.getHandle(key);
 }
 }
 
 
-bool BtRegistry::registerPeerStorage(const string& key,
-				     const PeerStorageHandle& peerStorage) {
-  PeerStorageMap::value_type p(key, peerStorage);
-  pair<PeerStorageMap::iterator, bool> retval = peerStorageMap.insert(p);
-  return retval.second;
+void BtRegistry::registerPeerStorage(const string& key,
+				     const PeerStorageHandle& peerStorage)
+{
+  peerStorageMap.registerHandle(key, peerStorage);
 }
 }
 				  
 				  
 PieceStorageHandle
 PieceStorageHandle
-BtRegistry::getPieceStorage(const string& key) {
-  PieceStorageMap::iterator itr = pieceStorageMap.find(key);
-  if(itr == pieceStorageMap.end()) {
-    return PieceStorageHandle(0);
-  } else {
-    return itr->second;
-  }
+BtRegistry::getPieceStorage(const string& key)
+{
+  return pieceStorageMap.getHandle(key);
 }
 }
 
 
-bool
+void
 BtRegistry::registerPieceStorage(const string& key,
 BtRegistry::registerPieceStorage(const string& key,
-				 const PieceStorageHandle& pieceStorage) {
-  pieceStorageMap.erase(key);
-  PieceStorageMap::value_type p(key, pieceStorage);
-  pair<PieceStorageMap::iterator, bool> retval = pieceStorageMap.insert(p);
-  return retval.second;
+				 const PieceStorageHandle& pieceStorage)
+{
+  pieceStorageMap.registerHandle(key, pieceStorage);
 }
 }
 
 
-BtRuntimeHandle BtRegistry::getBtRuntime(const string& key) {
-  BtRuntimeMap::iterator itr = btRuntimeMap.find(key);
-  if(itr == btRuntimeMap.end()) {
-    return BtRuntimeHandle(0);
-  } else {
-    return itr->second;
-  }
+BtRuntimeHandle BtRegistry::getBtRuntime(const string& key)
+{
+  return btRuntimeMap.getHandle(key);
 }
 }
 
 
-bool
+void
 BtRegistry::registerBtRuntime(const string& key,
 BtRegistry::registerBtRuntime(const string& key,
-			      const BtRuntimeHandle& btRuntime) {
-  BtRuntimeMap::value_type p(key, btRuntime);
-  pair<BtRuntimeMap::iterator, bool> retval =
-    btRuntimeMap.insert(p);
-  return retval.second;
+			      const BtRuntimeHandle& btRuntime)
+{
+  btRuntimeMap.registerHandle(key, btRuntime);
 }
 }
 
 
-BtAnnounceHandle BtRegistry::getBtAnnounce(const string& key) {
-  BtAnnounceMap::iterator itr = btAnnounceMap.find(key);
-  if(itr == btAnnounceMap.end()) {
-    return BtAnnounceHandle(0);
-  } else {
-    return itr->second;
-  }
+BtAnnounceHandle BtRegistry::getBtAnnounce(const string& key)
+{
+  return btAnnounceMap.getHandle(key);
 }
 }
 
 
-bool
+void
 BtRegistry::registerBtAnnounce(const string& key,
 BtRegistry::registerBtAnnounce(const string& key,
-			       const BtAnnounceHandle& btAnnounce) {
-  BtAnnounceMap::value_type p(key, btAnnounce);
-  pair<BtAnnounceMap::iterator, bool> retval =
-    btAnnounceMap.insert(p);
-  return retval.second;
+			       const BtAnnounceHandle& btAnnounce)
+{
+  btAnnounceMap.registerHandle(key, btAnnounce);
 }
 }
 
 
-BtProgressInfoFileHandle BtRegistry::getBtProgressInfoFile(const string& key) {
-  BtProgressInfoFileMap::iterator itr = btProgressInfoFileMap.find(key);
-  if(itr == btProgressInfoFileMap.end()) {
-    return BtProgressInfoFileHandle(0);
-  } else {
-    return itr->second;
-  }
+BtProgressInfoFileHandle BtRegistry::getBtProgressInfoFile(const string& key)
+{
+  return btProgressInfoFileMap.getHandle(key);
 }
 }
 
 
-bool
+void
 BtRegistry::registerBtProgressInfoFile(const string& key,
 BtRegistry::registerBtProgressInfoFile(const string& key,
-				       const BtProgressInfoFileHandle& btProgressInfoFile) {
-  BtProgressInfoFileMap::value_type p(key, btProgressInfoFile);
-  pair<BtProgressInfoFileMap::iterator, bool> retval =
-    btProgressInfoFileMap.insert(p);
-  return retval.second;
+				       const BtProgressInfoFileHandle& btProgressInfoFile)
+{
+  btProgressInfoFileMap.registerHandle(key, btProgressInfoFile);
+}
+
+BtContextHandle
+BtRegistry::getBtContext(const string& key)
+{
+  return btContextMap.getHandle(key);
+}
+
+void
+BtRegistry::registerBtContext(const string& key,
+			      const BtContextHandle& btContext)
+{
+  btContextMap.registerHandle(key, btContext);
 }
 }
 
 
 PeerObjectClusterHandle
 PeerObjectClusterHandle
@@ -150,7 +135,8 @@ BtRegistry::unregisterPeerObjectCluster(const string& key)
   peerObjectClusterRegistry.unregisterHandle(key);
   peerObjectClusterRegistry.unregisterHandle(key);
 }
 }
 
 
-void BtRegistry::clear() {
+void BtRegistry::unregisterAll() {
+  btContextMap.clear();
   peerStorageMap.clear();
   peerStorageMap.clear();
   pieceStorageMap.clear();
   pieceStorageMap.clear();
   btAnnounceMap.clear();
   btAnnounceMap.clear();
@@ -158,3 +144,14 @@ void BtRegistry::clear() {
   btProgressInfoFileMap.clear();
   btProgressInfoFileMap.clear();
   peerObjectClusterRegistry.clear();
   peerObjectClusterRegistry.clear();
 }
 }
+
+void BtRegistry::unregister(const string& key)
+{
+  btContextMap.unregisterHandle(key);
+  peerStorageMap.unregisterHandle(key);
+  pieceStorageMap.unregisterHandle(key);
+  btAnnounceMap.unregisterHandle(key);
+  btRuntimeMap.unregisterHandle(key);
+  btProgressInfoFileMap.unregisterHandle(key);
+  peerObjectClusterRegistry.unregisterHandle(key);
+}

+ 20 - 11
src/BtRegistry.h

@@ -36,6 +36,7 @@
 #define _D_BT_REGISTRY_H_
 #define _D_BT_REGISTRY_H_
 
 
 #include "common.h"
 #include "common.h"
+#include "BtContext.h"
 #include "PeerStorage.h"
 #include "PeerStorage.h"
 #include "PieceStorage.h"
 #include "PieceStorage.h"
 #include "BtAnnounce.h"
 #include "BtAnnounce.h"
@@ -45,11 +46,12 @@
 #include "HandleRegistry.h"
 #include "HandleRegistry.h"
 #include <map>
 #include <map>
 
 
-typedef map<string, PeerStorageHandle> PeerStorageMap;
-typedef map<string, PieceStorageHandle> PieceStorageMap;
-typedef map<string, BtAnnounceHandle> BtAnnounceMap;
-typedef map<string, BtRuntimeHandle> BtRuntimeMap;
-typedef map<string, BtProgressInfoFileHandle> BtProgressInfoFileMap;
+typedef HandleRegistry<string, PeerStorage> PeerStorageMap;
+typedef HandleRegistry<string, PieceStorage> PieceStorageMap;
+typedef HandleRegistry<string, BtAnnounce> BtAnnounceMap;
+typedef HandleRegistry<string, BtRuntime> BtRuntimeMap;
+typedef HandleRegistry<string, BtProgressInfoFile> BtProgressInfoFileMap;
+typedef HandleRegistry<string, BtContext>  BtContextMap;
 
 
 // for BtMessageFactory
 // for BtMessageFactory
 typedef HandleRegistry<string, PeerObject> PeerObjectCluster;
 typedef HandleRegistry<string, PeerObject> PeerObjectCluster;
@@ -60,6 +62,7 @@ class BtRegistry {
 private:
 private:
   BtRegistry() {}
   BtRegistry() {}
 
 
+  static BtContextMap btContextMap;
   static PeerStorageMap peerStorageMap;
   static PeerStorageMap peerStorageMap;
   static PieceStorageMap pieceStorageMap;
   static PieceStorageMap pieceStorageMap;
   static BtAnnounceMap btAnnounceMap;
   static BtAnnounceMap btAnnounceMap;
@@ -67,24 +70,28 @@ private:
   static BtProgressInfoFileMap btProgressInfoFileMap;
   static BtProgressInfoFileMap btProgressInfoFileMap;
   static PeerObjectClusterRegistry peerObjectClusterRegistry;
   static PeerObjectClusterRegistry peerObjectClusterRegistry;
 public:
 public:
+  static BtContextHandle getBtContext(const string& key);
+  static void registerBtContext(const string& key,
+				const BtContextHandle& btContext);
+
   static PeerStorageHandle getPeerStorage(const string& key);
   static PeerStorageHandle getPeerStorage(const string& key);
-  static bool registerPeerStorage(const string& key,
+  static void registerPeerStorage(const string& key,
 				  const PeerStorageHandle& peer);
 				  const PeerStorageHandle& peer);
 				  
 				  
   static PieceStorageHandle getPieceStorage(const string& key);
   static PieceStorageHandle getPieceStorage(const string& key);
-  static bool registerPieceStorage(const string& key,
+  static void registerPieceStorage(const string& key,
 				   const PieceStorageHandle& pieceStorage);
 				   const PieceStorageHandle& pieceStorage);
 
 
   static BtRuntimeHandle getBtRuntime(const string& key);
   static BtRuntimeHandle getBtRuntime(const string& key);
-  static bool registerBtRuntime(const string& key,
+  static void registerBtRuntime(const string& key,
 				const BtRuntimeHandle& btRuntime);
 				const BtRuntimeHandle& btRuntime);
 
 
   static BtAnnounceHandle getBtAnnounce(const string& key);
   static BtAnnounceHandle getBtAnnounce(const string& key);
-  static bool registerBtAnnounce(const string& key,
+  static void registerBtAnnounce(const string& key,
 				 const BtAnnounceHandle& btAnnounce);
 				 const BtAnnounceHandle& btAnnounce);
 
 
   static BtProgressInfoFileHandle getBtProgressInfoFile(const string& key);
   static BtProgressInfoFileHandle getBtProgressInfoFile(const string& key);
-  static bool registerBtProgressInfoFile(const string& key,
+  static void registerBtProgressInfoFile(const string& key,
 					 const BtProgressInfoFileHandle& btProgressInfoFile);
 					 const BtProgressInfoFileHandle& btProgressInfoFile);
 
 
   // for PeerObject
   // for PeerObject
@@ -98,7 +105,9 @@ public:
   static void
   static void
   unregisterPeerObjectCluster(const string& key);
   unregisterPeerObjectCluster(const string& key);
 
 
-  static void clear();
+  static void unregisterAll();
+
+  static void unregister(const string& key);
 };
 };
 
 
 #define PEER_STORAGE(btContext) \
 #define PEER_STORAGE(btContext) \

+ 8 - 2
src/BtRuntime.h

@@ -46,12 +46,14 @@ private:
   int32_t port;
   int32_t port;
   bool halt;
   bool halt;
   int32_t connections;
   int32_t connections;
+  bool _ready;
 public:
 public:
   BtRuntime():
   BtRuntime():
     uploadLengthAtStartup(0),
     uploadLengthAtStartup(0),
     port(0),
     port(0),
     halt(false),
     halt(false),
-    connections(0)
+    connections(0),
+    _ready(false)
     {}
     {}
   ~BtRuntime() {}
   ~BtRuntime() {}
 
 
@@ -83,7 +85,11 @@ public:
 
 
   bool lessThanMinPeer() const { return connections < MIN_PEERS; }
   bool lessThanMinPeer() const { return connections < MIN_PEERS; }
 
 
-  bool lessThanEqMinPeer() const { return connections <= MIN_PEERS; }  
+  bool lessThanEqMinPeer() const { return connections <= MIN_PEERS; }
+
+  bool ready() { return _ready; }
+
+  void setReady(bool go) { _ready = go; }
 };
 };
 
 
 typedef SharedHandle<BtRuntime> BtRuntimeHandle;
 typedef SharedHandle<BtRuntime> BtRuntimeHandle;

+ 97 - 0
src/BtSetup.cc

@@ -0,0 +1,97 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "BtSetup.h"
+#include "RequestGroup.h"
+#include "DownloadEngine.h"
+#include "Option.h"
+#include "BtRegistry.h"
+#include "PeerListenCommand.h"
+#include "TrackerWatcherCommand.h"
+#include "SeedCheckCommand.h"
+#include "PeerChokeCommand.h"
+#include "ActivePeerConnectionCommand.h"
+#include "UnionSeedCriteria.h"
+#include "TimeSeedCriteria.h"
+#include "ShareRatioSeedCriteria.h"
+#include "DefaultPieceStorage.h"
+#include "DefaultBtProgressInfoFile.h"
+#include "CUIDCounter.h"
+#include "prefs.h"
+
+Commands BtSetup::setup(RequestGroup* requestGroup,
+			DownloadEngine* e,
+			const Option* option)
+{
+  Commands commands;
+  BtContextHandle btContext = requestGroup->getDownloadContext();
+  if(btContext.isNull()) {
+    return commands;
+  }
+  // TODO following process is moved to BtSetup
+
+  // commands
+  commands.push_back(new TrackerWatcherCommand(CUIDCounterSingletonHolder::instance()->newID(),
+					       requestGroup,
+					       e,
+					       btContext));
+  commands.push_back(new PeerChokeCommand(CUIDCounterSingletonHolder::instance()->newID(),
+					  requestGroup,
+					  e,
+					  btContext,
+					  10));
+  commands.push_back(new ActivePeerConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(),
+						     requestGroup,
+						     e,
+						     btContext,
+						     30));
+
+  SharedHandle<UnionSeedCriteria> unionCri = new UnionSeedCriteria();
+  if(option->defined(PREF_SEED_TIME)) {
+    unionCri->addSeedCriteria(new TimeSeedCriteria(option->getAsInt(PREF_SEED_TIME)*60));
+  }
+  if(option->defined(PREF_SEED_RATIO)) {
+    unionCri->addSeedCriteria(new ShareRatioSeedCriteria(option->getAsDouble(PREF_SEED_RATIO), btContext));
+      }
+  if(unionCri->getSeedCriterion().size() > 0) {
+    commands.push_back(new SeedCheckCommand(CUIDCounterSingletonHolder::instance()->newID(),
+					    requestGroup,
+					    e,
+					    btContext,
+					    unionCri));
+  }
+
+  BT_RUNTIME(btContext)->setReady(true);
+  return commands;
+}

+ 14 - 12
src/DefaultFileAllocator.h → src/BtSetup.h

@@ -32,20 +32,22 @@
  * files in the program, then also delete it here.
  * files in the program, then also delete it here.
  */
  */
 /* copyright --> */
 /* copyright --> */
-#ifndef _D_DEFAULT_FILE_ALLOCATOR_H_
-#define _D_DEFAULT_FILE_ALLOCATOR_H_
+#ifndef _D_BT_SETUP_H_
+#define _D_BT_SETUP_H_
 
 
-#include "FileAllocator.h"
+#include "common.h"
 
 
-class DefaultFileAllocator : public FileAllocator {
-public:
-  DefaultFileAllocator() {}
-
-  virtual ~DefaultFileAllocator() {}
+class RequestGroup;
+class DownloadEngine;
+class Option;
+class Command;
+extern typedef deque<Command*> Commands;
 
 
-  virtual void allocate(int fd, int64_t totalLength);
+class BtSetup {
+public:
+  Commands setup(RequestGroup* requestGroup,
+		 DownloadEngine* e,
+		 const Option* option);
 };
 };
 
 
-typedef SharedHandle<DefaultFileAllocator> DefaultFileAllocatorHandle;
-
-#endif // _D_DEFAULT_FILE_ALLOCATOR_H_
+#endif // _D_BT_SETUP_H_

+ 17 - 15
src/ByteArrayDiskWriter.cc

@@ -38,34 +38,35 @@
 ByteArrayDiskWriter::ByteArrayDiskWriter() {
 ByteArrayDiskWriter::ByteArrayDiskWriter() {
 }
 }
 
 
-ByteArrayDiskWriter::~ByteArrayDiskWriter() {
-  closeFile();
-}
+ByteArrayDiskWriter::~ByteArrayDiskWriter() {}
 
 
-void ByteArrayDiskWriter::clear() {
+void ByteArrayDiskWriter::clear()
+{
   buf.str("");
   buf.str("");
 }
 }
 
 
 void ByteArrayDiskWriter::initAndOpenFile(const string& filename,
 void ByteArrayDiskWriter::initAndOpenFile(const string& filename,
-					  int64_t totalLength) {
+					  int64_t totalLength)
+{
   clear();
   clear();
 }
 }
 
 
 void ByteArrayDiskWriter::openFile(const string& filename,
 void ByteArrayDiskWriter::openFile(const string& filename,
-				   int64_t totalLength) {
-  initAndOpenFile(filename);
+				   int64_t totalLength)
+{
 }
 }
 
 
-void ByteArrayDiskWriter::closeFile() {
-  clear();
-}
+void ByteArrayDiskWriter::closeFile()
+{}
 
 
 void ByteArrayDiskWriter::openExistingFile(const string& filename,
 void ByteArrayDiskWriter::openExistingFile(const string& filename,
-					   int64_t totalLength) {
+					   int64_t totalLength)
+{
   openFile(filename);
   openFile(filename);
 }
 }
 
 
-void ByteArrayDiskWriter::writeData(const char* data, int32_t dataLength, int64_t position) {
+void ByteArrayDiskWriter::writeData(const unsigned char* data, int32_t dataLength, int64_t position)
+{
   if(size() < position) {
   if(size() < position) {
     buf.seekg(0, ios::end);
     buf.seekg(0, ios::end);
     for(int32_t i = size(); i < position; ++i) {
     for(int32_t i = size(); i < position; ++i) {
@@ -74,12 +75,13 @@ void ByteArrayDiskWriter::writeData(const char* data, int32_t dataLength, int64_
   } else {
   } else {
     buf.seekg(position, ios::beg);
     buf.seekg(position, ios::beg);
   }
   }
-  buf.write(data, dataLength);
+  buf.write(reinterpret_cast<const char*>(data), dataLength);
 }
 }
 
 
-int32_t ByteArrayDiskWriter::readData(char* data, int32_t len, int64_t position) {
+int32_t ByteArrayDiskWriter::readData(unsigned char* data, int32_t len, int64_t position)
+{
   buf.seekg(position, ios::beg);
   buf.seekg(position, ios::beg);
-  buf.read(data, len);
+  buf.read(reinterpret_cast<char*>(data), len);
   // TODO we have to call buf.clear() here? YES
   // TODO we have to call buf.clear() here? YES
   buf.clear();
   buf.clear();
   return buf.gcount();
   return buf.gcount();

+ 2 - 3
src/ByteArrayDiskWriter.h

@@ -55,9 +55,8 @@ public:
 
 
   virtual void openExistingFile(const string& filename, int64_t totalLength = 0);
   virtual void openExistingFile(const string& filename, int64_t totalLength = 0);
 
 
-  // position is ignored
-  virtual void writeData(const char* data, int32_t len, int64_t position = 0);
-  virtual int32_t readData(char* data, int32_t len, int64_t position);
+  virtual void writeData(const unsigned char* data, int32_t len, int64_t position);
+  virtual int32_t readData(unsigned char* data, int32_t len, int64_t position);
 
 
   // Not implemented yet
   // Not implemented yet
   virtual void truncate(int64_t length) {}
   virtual void truncate(int64_t length) {}

+ 52 - 0
src/ByteArrayDiskWriterFactory.h

@@ -0,0 +1,52 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_BYTE_ARRAY_DISK_WRITER_FACTORY_H_
+#define _D_BYTE_ARRAY_DISK_WRITER_FACTORY_H_
+
+#include "DiskWriterFactory.h"
+#include "ByteArrayDiskWriter.h"
+
+class ByteArrayDiskWriterFactory:public DiskWriterFactory
+{
+public:
+  DiskWriterHandle newDiskWriter()
+  {
+    return new ByteArrayDiskWriter();
+  }
+};
+
+typedef SharedHandle<ByteArrayDiskWriterFactory> ByteArrayDiskWriterFactoryHandle;
+
+#endif // _D_BYTE_ARRAY_DISK_WRITER_FACTORY_H_

+ 9 - 21
src/CheckIntegrityCommand.cc

@@ -33,6 +33,9 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "CheckIntegrityCommand.h"
 #include "CheckIntegrityCommand.h"
+#include "CheckIntegrityMan.h"
+#include "CheckIntegrityEntry.h"
+#include "RequestGroup.h"
 #include "FileAllocationEntry.h"
 #include "FileAllocationEntry.h"
 #include "InitiateConnectionCommandFactory.h"
 #include "InitiateConnectionCommandFactory.h"
 #include "DlAbortEx.h"
 #include "DlAbortEx.h"
@@ -40,7 +43,7 @@
 #include "DownloadCommand.h"
 #include "DownloadCommand.h"
 #include "prefs.h"
 #include "prefs.h"
 
 
-CheckIntegrityCommand::CheckIntegrityCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const CheckIntegrityEntryHandle& entry):
+CheckIntegrityCommand::CheckIntegrityCommand(int32_t cuid, RequestGroup* requestGroup, DownloadEngine* e, const CheckIntegrityEntryHandle& entry):
   RealtimeCommand(cuid, requestGroup, e),
   RealtimeCommand(cuid, requestGroup, e),
   _entry(entry)
   _entry(entry)
 {
 {
@@ -54,25 +57,16 @@ CheckIntegrityCommand::~CheckIntegrityCommand()
 
 
 bool CheckIntegrityCommand::executeInternal()
 bool CheckIntegrityCommand::executeInternal()
 {
 {
+  if(_requestGroup->isHaltRequested()) {
+    return true;
+  }
   _entry->validateChunk();
   _entry->validateChunk();
   if(_entry->finished()) {
   if(_entry->finished()) {
+    _entry->updatePieceStorage();
     if(_requestGroup->downloadFinished()) {
     if(_requestGroup->downloadFinished()) {
       logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, cuid, _requestGroup->getFilePath().c_str());
       logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, cuid, _requestGroup->getFilePath().c_str());
-      return true;
-    }
-    if(_requestGroup->needsFileAllocation()) {
-      FileAllocationEntryHandle entry = new FileAllocationEntry(cuid, _entry->getCurrentRequest(), _requestGroup, _entry->popNextDownloadCommand(), _requestGroup->getExistingFileLength());
-      _e->_fileAllocationMan->pushFileAllocationEntry(entry); 
     } else {
     } else {
-      if(_timer.difference() <= _e->option->getAsInt(PREF_DIRECT_DOWNLOAD_TIMEOUT) &&
-	 _entry->getNextDownloadCommand()) {
-	_e->commands.push_back(_entry->popNextDownloadCommand());
-      } else {
-	Commands commands = _requestGroup->createNextCommandWithAdj(_e, -1);
-	Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, _entry->getCurrentRequest(), _requestGroup, _e);
-	commands.push_front(command);
-	_e->addCommand(commands);
-      }
+      _e->addCommand(_entry->prepareForNextAction(_e));
     }
     }
     return true;
     return true;
   } else {
   } else {
@@ -84,12 +78,6 @@ bool CheckIntegrityCommand::executeInternal()
 bool CheckIntegrityCommand::handleException(Exception* e)
 bool CheckIntegrityCommand::handleException(Exception* e)
 {
 {
   logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid);
   logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid);
-  delete e;
   logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str());
   logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str());
-  // TODO this is wrong. There may exist invalid chunk data before catching
-  // exception. Fix this.
-  // The one of the solution is having a copy of bitfield before settting its
-  // all bit to 1. If exception is thrown, then assign the copy to the bitfield.
-  _requestGroup->markPieceDone(_entry->getCurrentLength());
   return true;
   return true;
 }
 }

+ 4 - 3
src/CheckIntegrityCommand.h

@@ -36,16 +36,17 @@
 #define _D_CHECK_INTEGRITY_COMMAND_H_
 #define _D_CHECK_INTEGRITY_COMMAND_H_
 
 
 #include "RealtimeCommand.h"
 #include "RealtimeCommand.h"
-#include "IteratableChunkChecksumValidator.h"
-#include "CheckIntegrityEntry.h"
 #include "TimeA2.h"
 #include "TimeA2.h"
 
 
+class CheckIntegrityEntry;
+extern typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
+
 class CheckIntegrityCommand : public RealtimeCommand {
 class CheckIntegrityCommand : public RealtimeCommand {
 private:
 private:
   CheckIntegrityEntryHandle _entry;
   CheckIntegrityEntryHandle _entry;
   Time _timer;
   Time _timer;
 public:
 public:
-  CheckIntegrityCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const CheckIntegrityEntryHandle& entry);
+  CheckIntegrityCommand(int32_t cuid, RequestGroup* requestGroup, DownloadEngine* e, const CheckIntegrityEntryHandle& entry);
 
 
   virtual ~CheckIntegrityCommand();
   virtual ~CheckIntegrityCommand();
 
 

+ 43 - 12
src/CheckIntegrityEntry.cc

@@ -34,33 +34,64 @@
 /* copyright --> */
 /* copyright --> */
 #include "CheckIntegrityEntry.h"
 #include "CheckIntegrityEntry.h"
 #include "DlAbortEx.h"
 #include "DlAbortEx.h"
+#include "Command.h"
+#include "RequestGroup.h"
+#include "IteratableChunkChecksumValidator.h"
+#include "DownloadContext.h"
+#include "DownloadEngine.h"
+
+CheckIntegrityEntry::CheckIntegrityEntry(RequestGroup* requestGroup,
+					 Command* nextCommand):
+  RequestGroupEntry(requestGroup, nextCommand),
+  _validator(0)
+{}
+
+CheckIntegrityEntry::~CheckIntegrityEntry() {}
 
 
 void CheckIntegrityEntry::validateChunk()
 void CheckIntegrityEntry::validateChunk()
 {
 {
   _validator->validateChunk();
   _validator->validateChunk();
 }
 }
 
 
-bool CheckIntegrityEntry::finished() const
+int64_t CheckIntegrityEntry::getTotalLength()
+{
+  if(_validator.isNull()) {
+    return 0;
+  } else {
+    return _validator->getTotalLength();
+  }
+}
+
+int64_t CheckIntegrityEntry::getCurrentLength()
+{
+  if(_validator.isNull()) {
+    return 0;
+  } else {
+    return _validator->getCurrentOffset();
+  }
+}
+
+bool CheckIntegrityEntry::finished()
 {
 {
   return _validator->finished();
   return _validator->finished();
 }
 }
 
 
-int64_t CheckIntegrityEntry::getCurrentLength() const
+bool CheckIntegrityEntry::isValidationReady()
 {
 {
-  return _validator->getCurrentOffset();
+  DownloadContextHandle dctx = _requestGroup->getDownloadContext();
+  return dctx->getPieceHashes().size() > 0 &&
+    dctx->getPieceHashes().size() == (uint32_t)dctx->getNumPieces();
 }
 }
 
 
 void CheckIntegrityEntry::initValidator()
 void CheckIntegrityEntry::initValidator()
 {
 {
   IteratableChunkChecksumValidatorHandle validator =
   IteratableChunkChecksumValidatorHandle validator =
-    new IteratableChunkChecksumValidator();
-  validator->setChunkChecksum(_requestGroup->getChunkChecksum());
-  validator->setDiskWriter(_requestGroup->getSegmentMan()->diskWriter);
-  validator->setBitfield(_requestGroup->getSegmentMan()->getBitfield());
-  if(!validator->canValidate()) {
-    // insufficient checksums.
-    throw new DlAbortEx("Insufficient checksums.");
-  }
-  validator->init();
+    new IteratableChunkChecksumValidator(_requestGroup->getDownloadContext(),
+					 _requestGroup->getPieceStorage());
   _validator = validator;
   _validator = validator;
 }
 }
+
+void CheckIntegrityEntry::updatePieceStorage()
+{
+  _validator->updatePieceStorage();
+}

+ 20 - 12
src/CheckIntegrityEntry.h

@@ -36,29 +36,37 @@
 #define _D_CHECK_INTEGRITY_ENTRY_H_
 #define _D_CHECK_INTEGRITY_ENTRY_H_
 
 
 #include "RequestGroupEntry.h"
 #include "RequestGroupEntry.h"
-#include "IteratableChunkChecksumValidator.h"
 
 
-class CheckIntegrityEntry : public RequestGroupEntry {
+class IteratableChunkChecksumValidator;
+extern typedef SharedHandle<IteratableChunkChecksumValidator> IteratableChunkChecksumValidatorHandle;
+class Command;
+extern typedef deque<Command*> Commands;
+class DownloadEngine;
+
+class CheckIntegrityEntry : public RequestGroupEntry,
+			    public ProgressAwareEntry {
 private:
 private:
   IteratableChunkChecksumValidatorHandle _validator;
   IteratableChunkChecksumValidatorHandle _validator;
 public:
 public:
-  CheckIntegrityEntry(int cuid,
-		      const RequestHandle& currentRequest,
-		      RequestGroup* requestGroup,
-		      DownloadCommand* nextDownloadCommand = 0):
-    RequestGroupEntry(cuid, currentRequest, requestGroup, nextDownloadCommand),
-    _validator(0)
-  {}
+  CheckIntegrityEntry(RequestGroup* requestGroup, Command* nextCommand = 0);
+
+  virtual ~CheckIntegrityEntry();
+
+  virtual int64_t getTotalLength();
 
 
-  virtual ~CheckIntegrityEntry() {}
+  virtual int64_t getCurrentLength();
 
 
-  virtual int64_t getCurrentLength() const;
+  virtual bool finished();
 
 
-  virtual bool finished() const;
+  bool isValidationReady();
 
 
   void initValidator();
   void initValidator();
 
 
   void validateChunk();
   void validateChunk();
+
+  void updatePieceStorage();
+
+  virtual Commands prepareForNextAction(DownloadEngine* e) = 0;
 };
 };
 
 
 typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
 typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;

+ 72 - 0
src/CheckIntegrityMan.cc

@@ -0,0 +1,72 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "CheckIntegrityMan.h"
+#include "CheckIntegrityEntry.h"
+
+CheckIntegrityMan::CheckIntegrityMan() {}
+
+CheckIntegrityMan::~CheckIntegrityMan() {}
+
+void CheckIntegrityMan::addCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry)
+{
+  _checkIntegrityEntries.push_back(entry);
+}
+
+bool CheckIntegrityMan::removeCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry)
+{
+  CheckIntegrityEntries::iterator itr = find(_checkIntegrityEntries.begin(),
+					     _checkIntegrityEntries.end(),
+					     entry);
+  if(itr == _checkIntegrityEntries.end()) {
+    return false;
+  } else {
+    _checkIntegrityEntries.erase(itr);
+    return true;
+  }
+}
+
+CheckIntegrityEntryHandle CheckIntegrityMan::getFirstCheckIntegrityEntry() const
+{
+  if(_checkIntegrityEntries.empty()) {
+    return 0;
+  } else {
+    return _checkIntegrityEntries.front();
+  }
+}
+
+int32_t CheckIntegrityMan::countCheckIntegrityEntry() const
+{
+  return _checkIntegrityEntries.size();
+}

+ 12 - 29
src/CheckIntegrityMan.h

@@ -36,43 +36,26 @@
 #define _D_CHECK_INTEGRITY_MAN_H_
 #define _D_CHECK_INTEGRITY_MAN_H_
 
 
 #include "common.h"
 #include "common.h"
-#include "CheckIntegrityEntry.h"
+
+class CheckIntegrityEntry;
+extern typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
+extern typedef deque<CheckIntegrityEntryHandle> CheckIntegrityEntries;
 
 
 class CheckIntegrityMan {
 class CheckIntegrityMan {
 private:
 private:
   CheckIntegrityEntries _checkIntegrityEntries;
   CheckIntegrityEntries _checkIntegrityEntries;
 public:
 public:
-  void addCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry)
-  {
-    _checkIntegrityEntries.push_back(entry);
-  }
+  CheckIntegrityMan();
+
+  ~CheckIntegrityMan();
+
+  void addCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry);
 
 
-  bool removeCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry)
-  {
-    CheckIntegrityEntries::iterator itr = find(_checkIntegrityEntries.begin(),
-					       _checkIntegrityEntries.end(),
-					       entry);
-    if(itr == _checkIntegrityEntries.end()) {
-      return false;
-    } else {
-      _checkIntegrityEntries.erase(itr);
-      return true;
-    }
-  }
+  bool removeCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry);
 
 
-  CheckIntegrityEntryHandle getFirstCheckIntegrityEntry() const
-  {
-    if(_checkIntegrityEntries.empty()) {
-      return 0;
-    } else {
-      return _checkIntegrityEntries.front();
-    }
-  }
+  CheckIntegrityEntryHandle getFirstCheckIntegrityEntry() const;
 
 
-  int32_t countCheckIntegrityEntry() const
-  {
-    return _checkIntegrityEntries.size();
-  }
+  int32_t countCheckIntegrityEntry() const;
 };
 };
 
 
 typedef SharedHandle<CheckIntegrityMan> CheckIntegrityManHandle;
 typedef SharedHandle<CheckIntegrityMan> CheckIntegrityManHandle;

+ 8 - 4
src/ChecksumCommand.cc

@@ -39,9 +39,11 @@
 void ChecksumCommand::initValidator()
 void ChecksumCommand::initValidator()
 {
 {
   _validator = new IteratableChecksumValidator();
   _validator = new IteratableChecksumValidator();
-  _validator->setChecksum(_requestGroup->getChecksum());
-  _validator->setDiskWriter(_requestGroup->getSegmentMan()->diskWriter);
-  _validator->setBitfield(_requestGroup->getSegmentMan()->getBitfield());
+  // TODO checksum will be held by DownloadContext
+  _validator->setChecksum(0);
+  //_validator->setDiskWriter(new DiskAdaptorWriter(_requestGroup->getSegmentMan()->getDiskAdaptor()));
+  // TODO we should use PieceStorage instead of BitfieldMan
+  //_validator->setBitfield(_requestGroup->getSegmentMan()->getBitfield());
   if(!_validator->canValidate()) {
   if(!_validator->canValidate()) {
     // insufficient checksums.
     // insufficient checksums.
     throw new DlAbortEx(EX_INSUFFICIENT_CHECKSUM);
     throw new DlAbortEx(EX_INSUFFICIENT_CHECKSUM);
@@ -51,6 +53,9 @@ void ChecksumCommand::initValidator()
 
 
 bool ChecksumCommand::executeInternal()
 bool ChecksumCommand::executeInternal()
 {
 {
+  if(_e->isHaltRequested()) {
+    return true;
+  }
   _validator->validateChunk();
   _validator->validateChunk();
   if(_validator->finished()) {
   if(_validator->finished()) {
     if(_requestGroup->downloadFinished()) {
     if(_requestGroup->downloadFinished()) {
@@ -70,7 +75,6 @@ bool ChecksumCommand::executeInternal()
 bool ChecksumCommand::handleException(Exception* e)
 bool ChecksumCommand::handleException(Exception* e)
 {
 {
   logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid);
   logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid);
-  delete e;
   logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str());
   logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str());
   // TODO We need to set bitfield back to the state when validation begun.
   // TODO We need to set bitfield back to the state when validation begun.
   // The one of the solution is having a copy of bitfield before settting its
   // The one of the solution is having a copy of bitfield before settting its

+ 2 - 2
src/ChecksumCommand.h

@@ -47,12 +47,12 @@ public:
     RealtimeCommand(cuid, requestGroup, e),
     RealtimeCommand(cuid, requestGroup, e),
     _validator(0)
     _validator(0)
   {
   {
-    ++_requestGroup->numConnection;
+    _requestGroup->increaseNumCommand();
   }
   }
 
 
   virtual ~ChecksumCommand()
   virtual ~ChecksumCommand()
   {
   {
-    --_requestGroup->numConnection;
+    _requestGroup->decreaseNumCommand();
   }
   }
 
 
   void initValidator();
   void initValidator();

+ 5 - 0
src/ChunkChecksum.h

@@ -79,6 +79,11 @@ public:
       return "";
       return "";
     }
     }
   }
   }
+  
+  const Strings& getChecksums() const
+  {
+    return _checksums;
+  }
 
 
   int32_t getChecksumLength() const
   int32_t getChecksumLength() const
   {
   {

+ 2 - 0
src/ChunkChecksumValidator.cc

@@ -38,6 +38,7 @@
 
 
 void ChunkChecksumValidator::validate()
 void ChunkChecksumValidator::validate()
 {
 {
+  /*
   if(!_validator->canValidate()) {
   if(!_validator->canValidate()) {
     // insufficient checksums.
     // insufficient checksums.
     logger->error(MSG_INSUFFICIENT_CHECKSUM,
     logger->error(MSG_INSUFFICIENT_CHECKSUM,
@@ -63,4 +64,5 @@ void ChunkChecksumValidator::validate()
   }
   }
   fileAllocationMonitor->setCurrentValue(numChecksum);
   fileAllocationMonitor->setCurrentValue(numChecksum);
   fileAllocationMonitor->showProgress();
   fileAllocationMonitor->showProgress();
+*/
 }
 }

+ 0 - 210
src/ConsoleDownloadEngine.cc

@@ -1,210 +0,0 @@
-/* <!-- copyright */
-/*
- * aria2 - The high speed download utility
- *
- * Copyright (C) 2006 Tatsuhiro Tsujikawa
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link the code of portions of this program with the
- * OpenSSL library under certain conditions as described in each
- * individual source file, and distribute linked combinations
- * including the two.
- * You must obey the GNU General Public License in all respects
- * for all of the code used other than OpenSSL.  If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so.  If you
- * do not wish to do so, delete this exception statement from your
- * version.  If you delete this exception statement from all source
- * files in the program, then also delete it here.
- */
-/* copyright --> */
-#include "ConsoleDownloadEngine.h"
-#include "Util.h"
-#include <signal.h>
-#include <iomanip>
-
-volatile sig_atomic_t haltRequested = 0;
-
-ConsoleDownloadEngine::ConsoleDownloadEngine() {}
-
-ConsoleDownloadEngine::~ConsoleDownloadEngine() {}
-
-void ConsoleDownloadEngine::sendStatistics(int64_t currentSize, int64_t totalSize) {
-  cout << "\r                                                                             ";
-  cout << "\r";
-  if(_requestGroupMan->countRequestGroup() > 0) {
-    RequestGroupHandle firstRequestGroup = _requestGroupMan->getRequestGroup(0);
-    int32_t dlSpeed = firstRequestGroup->calculateDownloadSpeed();
-    int32_t eta = 0;
-    if(firstRequestGroup->getTotalLength() > 0 && dlSpeed > 0) {
-      eta = (firstRequestGroup->getTotalLength()-firstRequestGroup->getDownloadLength())/dlSpeed;
-    }
-
-    cout << "["
-	 << "#" << firstRequestGroup->getGID() << " "
-	 << "SIZE:"
-	 << Util::abbrevSize(firstRequestGroup->getDownloadLength())
-	 << "B"
-	 << "/"
-	 << Util::abbrevSize(firstRequestGroup->getTotalLength())
-	 << "B";
-    if(firstRequestGroup->getTotalLength() > 0) {
-      cout << "("
-	   << 100*firstRequestGroup->getDownloadLength()/firstRequestGroup->getTotalLength()
-	   << "%)";
-    }
-    cout << " "
-	 << "CN:"
-	 << firstRequestGroup->numConnection;
-    cout << " "
-	 << "SPD:"
-	 << fixed << setprecision(2) << dlSpeed/1024.0 << "KiB/s";
-    if(eta > 0) {
-      cout << " "
-	   << "ETA:"
-	   << Util::secfmt(eta);
-    }
-    cout << "]";
-    if(_requestGroupMan->countRequestGroup() > 1) {
-      cout << "("
-	   << _requestGroupMan->countRequestGroup()-1
-	   << "more...)";
-    }
-  }
-
-  if(_requestGroupMan->countRequestGroup() > 1) {
-    cout << " "
-	 << "[TOTAL SPD:"
-	 << fixed << setprecision(2) << speed/1024.0 << "KiB/s" << "]";
-  }
-
-  {
-    FileAllocationEntryHandle entry = _fileAllocationMan->getCurrentFileAllocationEntry();
-    if(!entry.isNull()) {
-      cout << " "
-	   << "[FileAlloc:"
-	   << "#" << entry->getRequestGroup()->getGID() << " "
-	   << Util::abbrevSize(entry->getCurrentLength())
-	   << "B"
-	   << "/"
-	   << Util::abbrevSize(entry->getTotalLength())
-	   << "B"
-	   << "("
-	   << 100*entry->getCurrentLength()/entry->getTotalLength()
-	   << "%)";
-      cout << "]";
-      if(_fileAllocationMan->countFileAllocationEntryInQueue() > 0) {
-	cout << "("
-	     << _fileAllocationMan->countFileAllocationEntryInQueue()
-	     << "waiting...)";
-      }
-    }
-  }
-#ifdef ENABLE_MESSAGE_DIGEST
-  {
-    CheckIntegrityEntryHandle entry = _checkIntegrityMan->getFirstCheckIntegrityEntry();
-    if(!entry.isNull()) {
-      cout << " "
-	   << "[Checksum:"
-	   << "#" << entry->getRequestGroup()->getGID() << " "
-	   << Util::abbrevSize(entry->getCurrentLength())
-	   << "B"
-	   << "/"
-	   << Util::abbrevSize(entry->getTotalLength())
-	   << "B"
-	   << "("
-	   << 100*entry->getCurrentLength()/entry->getTotalLength()
-	   << "%)";
-      cout << "]";
-      if(_checkIntegrityMan->countCheckIntegrityEntry() > 1) {
-	cout << "("
-	     << _checkIntegrityMan->countCheckIntegrityEntry()-1
-	     << "more...)";
-      }
-    }
-  }
-#endif // ENABLE_MESSAGE_DIGEST
-  cout << flush;
-}
-
-void ConsoleDownloadEngine::initStatistics() {
-  cp.reset();
-  startup.reset();
-  speed = 0;
-  psize = 0;
-  avgSpeed = 0;
-  eta = 0;
-  startupLength = 0;
-  isStartupLengthSet = false;
-}
-
-void ConsoleDownloadEngine::calculateStatistics() {
-  int64_t dlSize = _requestGroupMan->getDownloadLength();
-  if(!isStartupLengthSet && dlSize > 0) {
-    startupLength = dlSize;
-    psize = dlSize;
-    isStartupLengthSet = true;
-  }
-  int32_t elapsed = cp.difference();
-  if(elapsed >= 1) {
-    int32_t nspeed = (dlSize-psize)/elapsed;
-    if(nspeed < 0) {
-      nspeed = 0;
-    }
-    speed = (nspeed+speed)/2;
-    cp.reset();
-    psize = dlSize;
-
-    int32_t elapsedFromStartup = startup.difference();
-    if(elapsedFromStartup > 0) {
-      avgSpeed = (dlSize-startupLength)/elapsedFromStartup;
-    }
-    int64_t totalLength = _requestGroupMan->getTotalLength();
-    if(avgSpeed < 0) {
-      avgSpeed = 0;
-    } else if(avgSpeed != 0 && totalLength > 0) {
-      eta = (totalLength-dlSize)/avgSpeed;
-    }
-    
-    sendStatistics(dlSize, totalLength);
-  }
-}
-
-void ConsoleDownloadEngine::onEndOfRun() {
-  _requestGroupMan->closeFile();
-//   if(segmentMan->finished()) {
-//     segmentMan->remove();
-//   } else {
-//     segmentMan->save();
-//   }
-}
-
-void ConsoleDownloadEngine::afterEachIteration() {
-  if(haltRequested) {
-    printf(_("\nstopping application...\n"));
-    fflush(stdout);
-    _requestGroupMan->save();
-    _requestGroupMan->closeFile();
-    printf(_("done\n"));
-    exit(EXIT_SUCCESS);
-  }
-}
-
-void ConsoleDownloadEngine::fillCommand()
-{
-  addCommand(_requestGroupMan->getInitialCommands(this));
-}

+ 162 - 0
src/ConsoleStatCalc.cc

@@ -0,0 +1,162 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "ConsoleStatCalc.h"
+#include "RequestGroupMan.h"
+#include "RequestGroup.h"
+#include "FileAllocationMan.h"
+#include "FileAllocationEntry.h"
+#include "CheckIntegrityMan.h"
+#include "CheckIntegrityEntry.h"
+#include "Util.h"
+#include <iomanip>
+
+void
+ConsoleStatCalc::calculateStat(const RequestGroupManHandle& requestGroupMan,
+			       const FileAllocationManHandle& fileAllocationMan,
+			       const CheckIntegrityManHandle& checkIntegrityMan)
+{
+  if(!_cp.elapsed(1)) {
+    return;
+  }
+  _cp.reset();
+
+  cout << "\r                                                                             ";
+  cout << "\r";
+  if(requestGroupMan->countRequestGroup() > 0) {
+    RequestGroupHandle firstRequestGroup = requestGroupMan->getRequestGroup(0);
+    TransferStat stat = firstRequestGroup->calculateStat();
+    //int32_t dlSpeed = firstRequestGroup->calculateDownloadSpeed();
+    int32_t eta = 0;
+    if(firstRequestGroup->getTotalLength() > 0 && stat.getDownloadSpeed() > 0) {
+      eta = (firstRequestGroup->getTotalLength()-firstRequestGroup->getCompletedLength())/stat.getDownloadSpeed();
+    }
+
+    cout << "["
+	 << "#" << firstRequestGroup->getGID() << " "
+	 << "SIZE:"
+	 << Util::abbrevSize(firstRequestGroup->getCompletedLength())
+	 << "B"
+	 << "/"
+	 << Util::abbrevSize(firstRequestGroup->getTotalLength())
+	 << "B";
+    if(firstRequestGroup->getTotalLength() > 0) {
+      cout << "("
+	   << 100*firstRequestGroup->getCompletedLength()/firstRequestGroup->getTotalLength()
+	   << "%)";
+    }
+    cout << " "
+	 << "CN:"
+	 << firstRequestGroup->getNumConnection();
+    cout << " "
+	 << "SPD:"
+	 << fixed << setprecision(2) << stat.getDownloadSpeed()/1024.0 << "KiB/s";
+    if(stat.getSessionUploadLength() > 0) {
+      cout << " "
+	   << "UP:"
+	   << fixed << setprecision(2) << stat.getUploadSpeed()/1024.0 << "KiB/s"
+	   << "(" << Util::abbrevSize(stat.getAllTimeUploadLength()) << ")";
+    }
+    if(eta > 0) {
+      cout << " "
+	   << "ETA:"
+	   << Util::secfmt(eta);
+    }
+    cout << "]";
+    if(requestGroupMan->countRequestGroup() > 1) {
+      cout << "("
+	   << requestGroupMan->countRequestGroup()-1
+	   << "more...)";
+    }
+  }
+
+  if(requestGroupMan->countRequestGroup() > 1) {
+    TransferStat stat = requestGroupMan->calculateStat();
+    cout << " "
+	 << "[TOTAL SPD:"
+	 << fixed << setprecision(2) << stat.getDownloadSpeed()/1024.0 << "KiB/s" << "]";
+  }
+
+  {
+    FileAllocationEntryHandle entry = fileAllocationMan->getCurrentFileAllocationEntry();
+    if(!entry.isNull()) {
+      cout << " "
+	   << "[FileAlloc:"
+	   << "#" << entry->getRequestGroup()->getGID() << " "
+	   << Util::abbrevSize(entry->getCurrentLength())
+	   << "B"
+	   << "/"
+	   << Util::abbrevSize(entry->getTotalLength())
+	   << "B"
+	   << "(";
+      if(entry->getTotalLength() > 0) {
+	cout << 100*entry->getCurrentLength()/entry->getTotalLength();
+      } else {
+	cout << "--";
+      }
+      cout << "%)"
+	   << "]";
+      if(fileAllocationMan->countFileAllocationEntryInQueue() > 0) {
+	cout << "("
+	     << fileAllocationMan->countFileAllocationEntryInQueue()
+	     << "waiting...)";
+      }
+    }
+  }
+#ifdef ENABLE_MESSAGE_DIGEST
+  {
+    CheckIntegrityEntryHandle entry = checkIntegrityMan->getFirstCheckIntegrityEntry();
+    if(!entry.isNull()) {
+      cout << " "
+	   << "[Checksum:"
+	   << "#" << entry->getRequestGroup()->getGID() << " "
+	   << Util::abbrevSize(entry->getCurrentLength())
+	   << "B"
+	   << "/"
+	   << Util::abbrevSize(entry->getTotalLength())
+	   << "B"
+	   << "("
+	   << 100*entry->getCurrentLength()/entry->getTotalLength()
+	   << "%)";
+      cout << "]";
+      if(checkIntegrityMan->countCheckIntegrityEntry() > 1) {
+	cout << "("
+	     << checkIntegrityMan->countCheckIntegrityEntry()-1
+	     << "more...)";
+      }
+    }
+  }
+#endif // ENABLE_MESSAGE_DIGEST
+  cout << flush;
+}

+ 14 - 10
src/TrackerSegmentManFactory.h → src/ConsoleStatCalc.h

@@ -32,20 +32,24 @@
  * files in the program, then also delete it here.
  * files in the program, then also delete it here.
  */
  */
 /* copyright --> */
 /* copyright --> */
-#ifndef _D_TRACKER_SEGMENT_MAN_FACTORY_H_
-#define _D_TRACKER_SEGMENT_MAN_FACTORY_H_
+#ifndef _D_CONSOLE_STAT_CALC_H_
+#define _D_CONSOLE_STAT_CALC_H_
 
 
-#include "AbstractSegmentManFactory.h"
+#include "StatCalc.h"
+#include "TimeA2.h"
 
 
-class TrackerSegmentManFactory : public AbstractSegmentManFactory {
+class ConsoleStatCalc:public StatCalc
+{
+private:
+  Time _cp;
 public:
 public:
-  TrackerSegmentManFactory(const Option* option):AbstractSegmentManFactory(option) {}
+  virtual ~ConsoleStatCalc() {}
 
 
-  virtual ~TrackerSegmentManFactory() {}
-
-  virtual SegmentManHandle createNewInstance();
+  virtual void calculateStat(const RequestGroupManHandle& requestGroupMan,
+			     const FileAllocationManHandle& fileAllocationMan,
+			     const CheckIntegrityManHandle& checkIntegrityMan);
 };
 };
 
 
-typedef SharedHandle<TrackerSegmentManFactory> TrackerSegmentManFactoryHandle;
+typedef SharedHandle<ConsoleStatCalc> ConsoleStatCalcHandle;
 
 
-#endif // _D_TRACKER_SEGMENT_MAN_FACTORY_H_
+#endif // _D_CONSOLE_STAT_CALC_H_

+ 8 - 3
src/CopyDiskAdaptor.cc

@@ -36,13 +36,17 @@
 #include "Util.h"
 #include "Util.h"
 #include "message.h"
 #include "message.h"
 
 
-void CopyDiskAdaptor::onDownloadComplete() {
+void CopyDiskAdaptor::onDownloadComplete()
+  throw(DlAbortEx*)
+{
   closeFile();
   closeFile();
   fixFilename();
   fixFilename();
   openFile();
   openFile();
 }
 }
 
 
-void CopyDiskAdaptor::fixFilename() {
+void CopyDiskAdaptor::fixFilename()
+  throw(DlAbortEx*)
+{
   int64_t offset = 0;
   int64_t offset = 0;
   for(FileEntries::iterator itr = fileEntries.begin();
   for(FileEntries::iterator itr = fileEntries.begin();
       itr != fileEntries.end(); itr++) {
       itr != fileEntries.end(); itr++) {
@@ -59,6 +63,7 @@ void CopyDiskAdaptor::fixFilename() {
   }
   }
 }
 }
 
 
-string CopyDiskAdaptor::getFilePath() {
+string CopyDiskAdaptor::getFilePath()
+{
   return storeDir+"/"+tempFilename;
   return storeDir+"/"+tempFilename;
 }
 }

+ 3 - 2
src/CopyDiskAdaptor.h

@@ -36,13 +36,14 @@
 #define _D_COPY_DISK_ADAPTOR_H_
 #define _D_COPY_DISK_ADAPTOR_H_
 
 
 #include "AbstractSingleDiskAdaptor.h"
 #include "AbstractSingleDiskAdaptor.h"
+#include "DlAbortEx.h"
 
 
 class CopyDiskAdaptor : public AbstractSingleDiskAdaptor {
 class CopyDiskAdaptor : public AbstractSingleDiskAdaptor {
 private:
 private:
   string tempFilename;
   string tempFilename;
   string topDir;
   string topDir;
 
 
-  void fixFilename();
+  void fixFilename() throw(DlAbortEx*);
 public:
 public:
   CopyDiskAdaptor() {}
   CopyDiskAdaptor() {}
 
 
@@ -50,7 +51,7 @@ public:
 
 
   virtual string getFilePath();
   virtual string getFilePath();
 
 
-  virtual void onDownloadComplete();
+  virtual void onDownloadComplete() throw(DlAbortEx*);
 
 
   // tempFilename is relative to storeDir
   // tempFilename is relative to storeDir
   void setTempFilename(const string& tempFilename) {
   void setTempFilename(const string& tempFilename) {

+ 7 - 1
src/DefaultBtContext.cc

@@ -42,9 +42,10 @@
 #include "Util.h"
 #include "Util.h"
 #include "MessageDigestHelper.h"
 #include "MessageDigestHelper.h"
 #include "a2netcompat.h"
 #include "a2netcompat.h"
+#include "AnnounceTier.h"
 #include <libgen.h>
 #include <libgen.h>
 
 
-DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-") {}
+DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-"), _ownerRequestGroup(0) {}
 
 
 DefaultBtContext::~DefaultBtContext() {}
 DefaultBtContext::~DefaultBtContext() {}
 
 
@@ -248,6 +249,11 @@ int32_t DefaultBtContext::getNumPieces() const {
   return numPieces;
   return numPieces;
 }
 }
 
 
+string DefaultBtContext::getActualBasePath() const
+{
+  return _dir+"/"+name;
+}
+
 Integers DefaultBtContext::computeFastSet(const string& ipaddr, int32_t fastSetSize)
 Integers DefaultBtContext::computeFastSet(const string& ipaddr, int32_t fastSetSize)
 {
 {
   Integers fastSet;
   Integers fastSet;

+ 19 - 1
src/DefaultBtContext.h

@@ -59,6 +59,8 @@ private:
   string _peerIdPrefix;
   string _peerIdPrefix;
   AnnounceTiers announceTiers;
   AnnounceTiers announceTiers;
 
 
+  RequestGroup* _ownerRequestGroup;
+
   void clear();
   void clear();
   void extractPieceHash(const unsigned char* hashData,
   void extractPieceHash(const unsigned char* hashData,
 			int32_t hashDataLength,
 			int32_t hashDataLength,
@@ -90,6 +92,11 @@ private:
 
 
   virtual FileEntries getFileEntries() const;
   virtual FileEntries getFileEntries() const;
 
 
+  virtual string getPieceHashAlgo() const
+  {
+    return "sha1";
+  }
+
   virtual AnnounceTiers getAnnounceTiers() const;
   virtual AnnounceTiers getAnnounceTiers() const;
 
 
   virtual void load(const string& torrentFile);
   virtual void load(const string& torrentFile);
@@ -100,6 +107,8 @@ private:
   
   
   virtual int32_t getNumPieces() const;
   virtual int32_t getNumPieces() const;
 
 
+  virtual string getActualBasePath() const;
+
   virtual const unsigned char* getPeerId() {
   virtual const unsigned char* getPeerId() {
     if(peerId == "") {
     if(peerId == "") {
       peerId = generatePeerId();
       peerId = generatePeerId();
@@ -109,6 +118,11 @@ private:
 
 
   virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize);
   virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize);
 
 
+  virtual RequestGroup* getOwnerRequestGroup()
+  {
+    return _ownerRequestGroup;
+  }
+
   string generatePeerId() const;
   string generatePeerId() const;
 
 
   void setPeerIdPrefix(const string& peerIdPrefix)
   void setPeerIdPrefix(const string& peerIdPrefix)
@@ -126,7 +140,11 @@ private:
   {
   {
     this->numPieces = numPieces;
     this->numPieces = numPieces;
   }
   }
-      
+   
+  void setOwnerRequestGroup(RequestGroup* owner)
+  {
+    _ownerRequestGroup = owner;
+  }
 };
 };
 
 
 typedef SharedHandle<DefaultBtContext> DefaultBtContextHandle;
 typedef SharedHandle<DefaultBtContext> DefaultBtContextHandle;

+ 198 - 93
src/DefaultBtProgressInfoFile.cc

@@ -33,6 +33,9 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "DefaultBtProgressInfoFile.h"
 #include "DefaultBtProgressInfoFile.h"
+#include "DownloadContext.h"
+#include "PieceStorage.h"
+#include "Option.h"
 #include "BtRegistry.h"
 #include "BtRegistry.h"
 #include "LogFactory.h"
 #include "LogFactory.h"
 #include "prefs.h"
 #include "prefs.h"
@@ -41,143 +44,245 @@
 #include "File.h"
 #include "File.h"
 #include "Util.h"
 #include "Util.h"
 #include "a2io.h"
 #include "a2io.h"
+#include <fstream>
 #include <errno.h>
 #include <errno.h>
 
 
-DefaultBtProgressInfoFile::DefaultBtProgressInfoFile(const BtContextHandle& btContext,
+DefaultBtProgressInfoFile::DefaultBtProgressInfoFile(const DownloadContextHandle& dctx,
+						     const PieceStorageHandle& pieceStorage,
 						     const Option* option):
 						     const Option* option):
-  btContext(btContext),
-  option(option),
-  pieceStorage(PIECE_STORAGE(btContext)),
-  btRuntime(BT_RUNTIME(btContext)),
-  peerStorage(PEER_STORAGE(btContext))
+  _dctx(dctx),
+  _pieceStorage(pieceStorage),
+  _option(option),
+  _logger(LogFactory::getInstance())
 {
 {
-  logger = LogFactory::getInstance();
-  string storeDir = option->get(PREF_DIR);
-  filename = storeDir+"/"+btContext->getName()+".aria2";
+  _filename = _dctx->getActualBasePath()+".aria2";
 }
 }
 
 
 DefaultBtProgressInfoFile::~DefaultBtProgressInfoFile() {}
 DefaultBtProgressInfoFile::~DefaultBtProgressInfoFile() {}
 
 
+bool DefaultBtProgressInfoFile::isTorrentDownload()
+{
+  return !BtContextHandle(_dctx).isNull();
+}
+
 void DefaultBtProgressInfoFile::save() {
 void DefaultBtProgressInfoFile::save() {
-  logger->info(MSG_SAVING_SEGMENT_FILE, filename.c_str());
-  string filenameTemp = filename+"__temp";
-  FILE* file = openFile(filenameTemp, "wb");
+  _logger->info(MSG_SAVING_SEGMENT_FILE, _filename.c_str());
+  string filenameTemp = _filename+"__temp";
+  ofstream o(filenameTemp.c_str(), ios::out|ios::binary);
+  o.exceptions(ios::failbit);
   try {
   try {
-    if(fwrite(btContext->getInfoHash(),
-	      btContext->getInfoHashLength(), 1, file) < 1) {
-      throw string("writeError:info hash");
+    bool torrentDownload = isTorrentDownload();
+    // file version: 16 bits
+    // value: '0'
+    int16_t version = 0;
+    o.write(reinterpret_cast<const char*>(&version), sizeof(int16_t));
+    // extension: 32 bits
+    // If this is BitTorrent download, then 0x00000001
+    // Otherwise, 0x00000000
+    char extension[4];
+    memset(extension, 0, sizeof(extension));
+    if(torrentDownload) {
+      extension[3] = 1;
     }
     }
-    if(fwrite(pieceStorage->getBitfield(),
-	      pieceStorage->getBitfieldLength(), 1, file) < 1) {
-      throw string("writeError:bitfield");
+    o.write(reinterpret_cast<const char*>(&extension), sizeof(extension));
+    if(torrentDownload) {
+      // infoHashLength:
+      // length: 32 bits
+      BtContextHandle btContext = _dctx;
+      int32_t infoHashLength = btContext->getInfoHashLength();
+      o.write(reinterpret_cast<const char*>(&infoHashLength), sizeof(int32_t));
+      // infoHash:
+      o.write(reinterpret_cast<const char*>(btContext->getInfoHash()),
+	      btContext->getInfoHashLength());
+    } else {
+      // infoHashLength:
+      // length: 32 bits
+      int32_t infoHashLength = 0;
+      o.write(reinterpret_cast<const char*>(&infoHashLength), sizeof(int32_t));
     }
     }
-    TransferStat stat = peerStorage->calculateStat();
-    int64_t allTimeDownloadLength = pieceStorage->getCompletedLength();
-    if(fwrite(&allTimeDownloadLength,
-	      sizeof(allTimeDownloadLength), 1, file) < 1) {
-      throw string("writeError:download length");
+    // pieceLength: 32 bits
+    int32_t pieceLength = _dctx->getPieceLength();
+    o.write(reinterpret_cast<const char*>(&pieceLength), sizeof(int32_t));
+    // totalLength: 64 bits
+    int64_t totalLength = _dctx->getTotalLength();
+    o.write(reinterpret_cast<const char*>(&totalLength), sizeof(int64_t));
+    // uploadLength: 64 bits
+    int64_t uploadLength = 0;
+    if(torrentDownload) {
+      BtContextHandle btContext = _dctx;
+      TransferStat stat = PEER_STORAGE(btContext)->calculateStat();
+      uploadLength = stat.getAllTimeUploadLength();
     }
     }
-    int64_t allTimeUploadLength =
-      btRuntime->getUploadLengthAtStartup()+
-      stat.getSessionUploadLength();
-    if(fwrite(&allTimeUploadLength,
-	      sizeof(allTimeUploadLength), 1, file) < 1) {
-      throw string("writeError:upload length");
+    o.write(reinterpret_cast<const char*>(&uploadLength), sizeof(int64_t));
+    // bitfieldLength: 32 bits
+    int32_t bitfieldLength = _pieceStorage->getBitfieldLength();
+    o.write(reinterpret_cast<const char*>(&bitfieldLength), sizeof(int32_t));
+    // bitfield
+    o.write(reinterpret_cast<const char*>(_pieceStorage->getBitfield()), _pieceStorage->getBitfieldLength());
+    // the number of in-flight piece: 32 bits
+    // TODO implement this
+    int32_t numInFlightPiece = _pieceStorage->countInFlightPiece();
+    o.write(reinterpret_cast<const char*>(&numInFlightPiece), sizeof(int32_t));
+    Pieces inFlightPieces = _pieceStorage->getInFlightPieces();
+    for(Pieces::const_iterator itr = inFlightPieces.begin();
+	itr != inFlightPieces.end(); ++itr) {
+      int32_t index = (*itr)->getIndex();
+      o.write(reinterpret_cast<const char*>(&index), sizeof(int32_t));
+      int32_t length = (*itr)->getLength();
+      o.write(reinterpret_cast<const char*>(&length), sizeof(int32_t));
+      int32_t bitfieldLength = (*itr)->getBitfieldLength();
+      o.write(reinterpret_cast<const char*>(&bitfieldLength), sizeof(int32_t));
+      o.write(reinterpret_cast<const char*>((*itr)->getBitfield()), bitfieldLength);
     }
     }
-    fclose(file);
-    logger->info(MSG_SAVED_SEGMENT_FILE);
-  } catch(string ex) {
-    fclose(file);
+
+    o.close();
+    _logger->info(MSG_SAVED_SEGMENT_FILE);
+  } catch(ios::failure const& exception) {
+    // TODO ios::failure doesn't give us the reasons of failure...
     throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
     throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
-			filename.c_str(), strerror(errno));
+			_filename.c_str(), strerror(errno));
   }
   }
-
-  if(rename(filenameTemp.c_str(), filename.c_str()) == -1) {
+  if(rename(filenameTemp.c_str(), _filename.c_str()) == -1) {
     throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
     throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
-			filename.c_str(), strerror(errno));
+			_filename.c_str(), strerror(errno));
   }
   }
 }
 }
 
 
-void DefaultBtProgressInfoFile::load() {
-  logger->info(MSG_LOADING_SEGMENT_FILE, filename.c_str());
-  FILE* file = openFile(filename, "r+b");
+void DefaultBtProgressInfoFile::load() 
+{
+  _logger->info(MSG_LOADING_SEGMENT_FILE, _filename.c_str());
+  ifstream in(_filename.c_str(), ios::in|ios::binary);
+  in.exceptions(ios::failbit);
   unsigned char* savedInfoHash = 0;
   unsigned char* savedInfoHash = 0;
   unsigned char* savedBitfield = 0;
   unsigned char* savedBitfield = 0;
   try {
   try {
-    savedInfoHash = new unsigned char[btContext->getInfoHashLength()];
-    savedBitfield = new unsigned char[pieceStorage->getBitfieldLength()];
-    if(fread(savedInfoHash, btContext->getInfoHashLength(), 1, file) < 1) {
-      throw string("readError");
+    unsigned char version[2];
+    in.read((char*)version, sizeof(version));
+    if(string("0000") != Util::toHex(version, sizeof(version))) {
+      throw new DlAbortEx("Unsupported ctrl file version: %s",
+			  Util::toHex(version, sizeof(version)).c_str());
+    }
+    unsigned char extension[4];
+    in.read((char*)extension, sizeof(extension));
+
+    bool infoHashCheckEnabled = false;
+    if(extension[3]&1 && isTorrentDownload()) {
+      infoHashCheckEnabled = true;
+      _logger->debug("InfoHash checking enabled.");
+    }
+
+    int32_t infoHashLength;
+    in.read(reinterpret_cast<char*>(&infoHashLength), sizeof(infoHashLength));
+    if(infoHashLength < 0 || infoHashLength == 0 && infoHashCheckEnabled) {
+      throw new DlAbortEx("Invalid info hash length: %d", infoHashLength);
+    }
+    if(infoHashLength > 0) {
+      savedInfoHash = new unsigned char[infoHashLength];
+      in.read(reinterpret_cast<char*>(savedInfoHash), infoHashLength);
+      BtContextHandle btContext = _dctx;
+      if(infoHashCheckEnabled &&
+	 Util::toHex(savedInfoHash, infoHashLength) != btContext->getInfoHashAsString()) {
+	throw new DlAbortEx("info hash mismatch. expected: %s, actual: %s",
+			    btContext->getInfoHashAsString().c_str(),
+			    Util::toHex(savedInfoHash, infoHashLength).c_str());
+      }
+      delete [] savedInfoHash;
+      savedInfoHash = 0;
     }
     }
-    if(Util::toHex(savedInfoHash, btContext->getInfoHashLength()) != 
-       btContext->getInfoHashAsString()) {
-      throw string("infoHashMismatch");
+
+    // TODO implement the conversion mechanism between different piece length.
+    int32_t pieceLength;
+    in.read(reinterpret_cast<char*>(&pieceLength), sizeof(pieceLength));
+    if(pieceLength != _dctx->getPieceLength()) {
+      throw new DlAbortEx("piece length mismatch. expected: %d, actual: %d",
+			  _dctx->getPieceLength(), pieceLength);
     }
     }
-    if(fread(savedBitfield, pieceStorage->getBitfieldLength(), 1, file) < 1) {
-      throw string("readError");
+
+    int64_t totalLength;
+    in.read(reinterpret_cast<char*>(&totalLength), sizeof(totalLength));
+    if(totalLength != _dctx->getTotalLength()) {
+      throw new DlAbortEx("total length mismatch. expected: %s, actual: %s",
+			  Util::llitos(_dctx->getTotalLength()).c_str(),
+			  Util::llitos(totalLength).c_str());
     }
     }
-    pieceStorage->setBitfield(savedBitfield,
-			      pieceStorage->getBitfieldLength());
-    // allTimeDownloadLength exists for only a compatibility reason.
-    int64_t allTimeDownloadLength;
-    if(fread(&allTimeDownloadLength,
-	     sizeof(allTimeDownloadLength), 1, file) < 1) {
-      throw string("readError");
+    int64_t uploadLength;
+    in.read(reinterpret_cast<char*>(&uploadLength), sizeof(uploadLength));
+    if(isTorrentDownload()) {
+      BT_RUNTIME(BtContextHandle(_dctx))->setUploadLengthAtStartup(uploadLength);
     }
     }
-    int64_t allTimeUploadLength;
-    if(fread(&allTimeUploadLength,
-	     sizeof(allTimeUploadLength), 1, file) < 1) {
-      throw string("readError");
+
+    // TODO implement the conversion mechanism between different piece length.
+    int32_t bitfieldLength;
+    in.read(reinterpret_cast<char*>(&bitfieldLength), sizeof(bitfieldLength));
+    if(_pieceStorage->getBitfieldLength() != bitfieldLength) {
+      throw new DlAbortEx("bitfield length mismatch. expected: %d, actual: %d",
+			  _pieceStorage->getBitfieldLength(),
+			  bitfieldLength);
     }
     }
-    btRuntime->setUploadLengthAtStartup(allTimeUploadLength);
+
+    // TODO implement the conversion mechanism between different piece length.
+    savedBitfield = new unsigned char[bitfieldLength];
+    in.read(reinterpret_cast<char*>(savedBitfield), bitfieldLength);
+    _pieceStorage->setBitfield(savedBitfield, bitfieldLength);
     delete [] savedBitfield;
     delete [] savedBitfield;
     savedBitfield = 0;
     savedBitfield = 0;
-    delete [] savedInfoHash;
-    savedInfoHash = 0;
-    fclose(file);
-  } catch(string ex) {
-    if(savedBitfield) {
+
+    int32_t numInFlightPiece;
+    in.read(reinterpret_cast<char*>(&numInFlightPiece), sizeof(numInFlightPiece));
+    
+    Pieces inFlightPieces;
+    while(numInFlightPiece--) {
+      int32_t index;
+      in.read(reinterpret_cast<char*>(&index), sizeof(index));
+      if(!(0 <= index && index < _dctx->getNumPieces())) {
+	throw new DlAbortEx("piece index out of range: %d", index);
+      }
+      int32_t length;
+      in.read(reinterpret_cast<char*>(&length), sizeof(length));
+      if(!(0 < length && length <=_dctx->getPieceLength())) {
+	throw new DlAbortEx("piece length out of range: %d", length);
+      }
+      PieceHandle piece = new Piece(index, length);
+      int32_t bitfieldLength;
+      in.read(reinterpret_cast<char*>(&bitfieldLength), sizeof(bitfieldLength));
+      if(piece->getBitfieldLength() != bitfieldLength) {
+	throw new DlAbortEx("piece bitfield length mismatch. expected: %d actual: %d",
+			    piece->getBitfieldLength(), bitfieldLength);
+      }
+      savedBitfield = new unsigned char[bitfieldLength];
+      in.read(reinterpret_cast<char*>(savedBitfield), bitfieldLength);
+      piece->setBitfield(savedBitfield, bitfieldLength);
       delete [] savedBitfield;
       delete [] savedBitfield;
+      savedBitfield = 0;
+      
+      inFlightPieces.push_back(piece);
     }
     }
-    if(savedInfoHash) {
-      delete [] savedInfoHash;
-    }
-    fclose(file);
-    if(ex == "infoHashMismatch") {
-      throw new DlAbortEx(EX_INFOHASH_MISMATCH_IN_SEGFILE);
-    } else {
-      throw new DlAbortEx(EX_SEGMENT_FILE_READ,
-			  filename.c_str(), strerror(errno));
-    }
-  }
-  logger->info(MSG_LOADED_SEGMENT_FILE);
+    _pieceStorage->addInFlightPiece(inFlightPieces);
+
+    _logger->info(MSG_LOADED_SEGMENT_FILE);
+  } catch(ios::failure const& exception) {
+    delete [] savedBitfield;
+    delete [] savedInfoHash;
+    // TODO ios::failure doesn't give us the reasons of failure...
+    throw new DlAbortEx(EX_SEGMENT_FILE_READ,
+			_filename.c_str(), strerror(errno));
+  } 
 }
 }
 
 
 void DefaultBtProgressInfoFile::removeFile() {
 void DefaultBtProgressInfoFile::removeFile() {
   if(exists()) {
   if(exists()) {
-    File f(filename);
+    File f(_filename);
     f.remove();
     f.remove();
   }
   }
 }
 }
 
 
-FILE* DefaultBtProgressInfoFile::openFile(const string& filename,
-					  const string& mode) const
-{
-  FILE* file = fopen(filename.c_str(), mode.c_str());
-  if(!file) {
-    throw new DlAbortEx(EX_SEGMENT_FILE_OPEN,
-			filename.c_str(), strerror(errno));
-  }
-  return file;
-}
-
 bool DefaultBtProgressInfoFile::exists() {
 bool DefaultBtProgressInfoFile::exists() {
-  File f(filename);
+  File f(_filename);
   if(f.isFile()) {
   if(f.isFile()) {
-    logger->info(MSG_SEGMENT_FILE_EXISTS, filename.c_str());
+    _logger->info(MSG_SEGMENT_FILE_EXISTS, _filename.c_str());
     return true;
     return true;
   } else {
   } else {
-    logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, filename.c_str());
+    _logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, _filename.c_str());
     return false;
     return false;
   }
   }
 }
 }

+ 19 - 35
src/DefaultBtProgressInfoFile.h

@@ -36,49 +36,33 @@
 #define _D_DEFAULT_BT_PROGRESS_INFO_FILE_H_
 #define _D_DEFAULT_BT_PROGRESS_INFO_FILE_H_
 
 
 #include "BtProgressInfoFile.h"
 #include "BtProgressInfoFile.h"
-#include "BtContext.h"
-#include "PieceStorage.h"
-#include "BtRuntime.h"
-#include "PeerStorage.h"
-#include "Logger.h"
-#include "Option.h"
+
+class DownloadContext;
+extern typedef SharedHandle<DownloadContext> DownloadContextHandle;
+class PieceStorage;
+extern typedef SharedHandle<PieceStorage> PieceStorageHandle;
+class Logger;
+class Option;
 
 
 class DefaultBtProgressInfoFile : public BtProgressInfoFile {
 class DefaultBtProgressInfoFile : public BtProgressInfoFile {
 private:
 private:
-  BtContextHandle btContext;
-  const Option* option;
-  Logger* logger;
-  PieceStorageHandle pieceStorage;
-  BtRuntimeHandle btRuntime;
-  PeerStorageHandle peerStorage;
-  string filename;
+  DownloadContextHandle _dctx;
+  PieceStorageHandle _pieceStorage;
+  const Option* _option;
+  const Logger* _logger;
+  string _filename;
+
+  bool isTorrentDownload();
 
 
-  FILE* openFile(const string& filename, const string& mode) const;
 public:
 public:
-  DefaultBtProgressInfoFile(const BtContextHandle& btContext,
+  DefaultBtProgressInfoFile(const DownloadContextHandle& btContext,
+			    const PieceStorageHandle& pieceStorage,
 			    const Option* option);
 			    const Option* option);
-  virtual ~DefaultBtProgressInfoFile();
-
-  void setBtRuntime(const BtRuntimeHandle& btRuntime) {
-    this->btRuntime = btRuntime;
-  }
-  BtRuntimeHandle getBtRuntime() const { return btRuntime; }
 
 
-  void setPieceStorage(const PieceStorageHandle& pieceStorage) {
-    this->pieceStorage = pieceStorage;
-  }
-  PieceStorageHandle getPieceStorage() const { return pieceStorage; }
-
-  void setPeerStorage(const PeerStorageHandle& peerStorage) {
-    this->peerStorage = peerStorage;
-  }
-  PeerStorageHandle getPeerStorage() const { return peerStorage; }
-
-  virtual void setFilename(const string& filename) {
-    this->filename = filename;
-  }
-  virtual string getFilename() { return filename; }
+  virtual ~DefaultBtProgressInfoFile();
 
 
+  virtual string getFilename() { return _filename; }
+  
   virtual bool exists();
   virtual bool exists();
 
 
   virtual void save();
   virtual void save();

+ 1 - 35
src/DefaultDiskWriter.cc

@@ -33,10 +33,7 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "DefaultDiskWriter.h"
 #include "DefaultDiskWriter.h"
-#include "DlAbortEx.h"
 #include "message.h"
 #include "message.h"
-#include "DefaultFileAllocator.h"
-#include "GlowFileAllocator.h"
 #include "prefs.h"
 #include "prefs.h"
 #include "Util.h"
 #include "Util.h"
 #include <errno.h>
 #include <errno.h>
@@ -48,38 +45,7 @@ DefaultDiskWriter::~DefaultDiskWriter() {}
 
 
 void DefaultDiskWriter::initAndOpenFile(const string& filename,
 void DefaultDiskWriter::initAndOpenFile(const string& filename,
 					int64_t totalLength)
 					int64_t totalLength)
+  throw(DlAbortEx*)
 {
 {
   createFile(filename);
   createFile(filename);
-  try {
-    if(totalLength > 0) {
-      if(fileAllocator.isNull()) {
-	ftruncate(fd, 0);
-      } else {
-	logger->notice(MSG_ALLOCATING_FILE,
-		       filename.c_str(),
-		       Util::ullitos(totalLength).c_str());
-	fileAllocator->allocate(fd, totalLength);
-      }
-    }
-  } catch(RecoverableException *e) {
-    throw new DlAbortEx(e, EX_FILE_WRITE, filename.c_str(), strerror(errno));
-  }
-}
-
-DefaultDiskWriter* DefaultDiskWriter::createNewDiskWriter(const Option* option)
-{
-  DefaultDiskWriter* diskWriter = new DefaultDiskWriter();
-  if(option->get(PREF_FILE_ALLOCATION) == V_PREALLOC) {
-    DefaultFileAllocatorHandle allocator = new DefaultFileAllocator();
-    allocator->setFileAllocationMonitor(FileAllocationMonitorFactory::getFactory()->createNewMonitor());
-    diskWriter->setFileAllocator(allocator);
-
-    GlowFileAllocatorHandle glowAllocator = new GlowFileAllocator();
-    glowAllocator->setFileAllocationMonitor(FileAllocationMonitorFactory::getFactory()->createNewMonitor());
-    diskWriter->setGlowFileAllocator(glowAllocator);
-  } else {
-    diskWriter->setFileAllocator(0);
-    diskWriter->setGlowFileAllocator(0);
-  }
-  return diskWriter;
 }
 }

+ 2 - 3
src/DefaultDiskWriter.h

@@ -37,6 +37,7 @@
 
 
 #include "AbstractDiskWriter.h"
 #include "AbstractDiskWriter.h"
 #include "Option.h"
 #include "Option.h"
+#include "DlAbortEx.h"
 
 
 class DefaultDiskWriter:public AbstractDiskWriter {
 class DefaultDiskWriter:public AbstractDiskWriter {
 public:
 public:
@@ -45,9 +46,7 @@ public:
   virtual ~DefaultDiskWriter();
   virtual ~DefaultDiskWriter();
 
 
   virtual void initAndOpenFile(const string& filename,
   virtual void initAndOpenFile(const string& filename,
-			       int64_t totalLength = 0);
-
-  static DefaultDiskWriter* createNewDiskWriter(const Option* option);
+			       int64_t totalLength = 0) throw(DlAbortEx*);
 };
 };
 
 
 typedef SharedHandle<DefaultDiskWriter> DefaultDiskWriterHandle;
 typedef SharedHandle<DefaultDiskWriter> DefaultDiskWriterHandle;

+ 52 - 0
src/DefaultDiskWriterFactory.h

@@ -0,0 +1,52 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DEFAULT_DISK_WRITER_FACTORY_H_
+#define _D_DEFAULT_DISK_WRITER_FACTORY_H_
+
+#include "DiskWriterFactory.h"
+#include "DefaultDiskWriter.h"
+
+class DefaultDiskWriterFactory:public DiskWriterFactory
+{
+public:
+  DiskWriterHandle newDiskWriter()
+  {
+    return new DefaultDiskWriter();
+  }
+};
+
+typedef SharedHandle<DefaultDiskWriterFactory> DefaultDiskWriterFactoryHandle;
+
+#endif // _D_DEFAULT_DISK_WRITER_FACTORY_H_

+ 2 - 0
src/DefaultPeerStorage.cc

@@ -192,6 +192,8 @@ TransferStat DefaultPeerStorage::calculateStat() {
   TransferStat stat = calStat.getTransferStat();
   TransferStat stat = calStat.getTransferStat();
   stat.sessionDownloadLength += removedPeerSessionDownloadLength;
   stat.sessionDownloadLength += removedPeerSessionDownloadLength;
   stat.sessionUploadLength += removedPeerSessionUploadLength;
   stat.sessionUploadLength += removedPeerSessionUploadLength;
+  stat.setAllTimeUploadLength(btRuntime->getUploadLengthAtStartup()+
+			      stat.getSessionUploadLength());
   return stat;
   return stat;
 }
 }
 
 

+ 157 - 83
src/DefaultPieceStorage.cc

@@ -33,29 +33,31 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "DefaultPieceStorage.h"
 #include "DefaultPieceStorage.h"
+#include "DownloadContext.h"
+#include "Piece.h"
+#include "Peer.h"
 #include "LogFactory.h"
 #include "LogFactory.h"
 #include "prefs.h"
 #include "prefs.h"
 #include "DirectDiskAdaptor.h"
 #include "DirectDiskAdaptor.h"
 #include "MultiDiskAdaptor.h"
 #include "MultiDiskAdaptor.h"
 #include "CopyDiskAdaptor.h"
 #include "CopyDiskAdaptor.h"
-#include "DefaultDiskWriter.h"
-#include "DlAbortEx.h"
+#include "DiskWriter.h"
 #include "BitfieldManFactory.h"
 #include "BitfieldManFactory.h"
-#include "FileAllocationMonitor.h"
-#include "DiskAdaptorWriter.h"
-#include "ChunkChecksumValidator.h"
 #include "message.h"
 #include "message.h"
+#include "DefaultDiskWriterFactory.h"
+#include "DlAbortEx.h"
 
 
-DefaultPieceStorage::DefaultPieceStorage(BtContextHandle btContext, const Option* option):
-  btContext(btContext),
+DefaultPieceStorage::DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option):
+  downloadContext(downloadContext),
   diskAdaptor(0),
   diskAdaptor(0),
+  _diskWriterFactory(new DefaultDiskWriterFactory()),
   endGamePieceNum(END_GAME_PIECE_NUM),
   endGamePieceNum(END_GAME_PIECE_NUM),
   option(option)
   option(option)
 {
 {
   bitfieldMan =
   bitfieldMan =
     BitfieldManFactory::getFactoryInstance()->
     BitfieldManFactory::getFactoryInstance()->
-    createBitfieldMan(btContext->getPieceLength(),
-		      btContext->getTotalLength());
+    createBitfieldMan(downloadContext->getPieceLength(),
+		      downloadContext->getTotalLength());
   logger = LogFactory::getInstance();
   logger = LogFactory::getInstance();
 }
 }
 
 
@@ -63,16 +65,19 @@ DefaultPieceStorage::~DefaultPieceStorage() {
   delete bitfieldMan;
   delete bitfieldMan;
 }
 }
 
 
-bool DefaultPieceStorage::hasMissingPiece(const PeerHandle& peer) {
+bool DefaultPieceStorage::hasMissingPiece(const PeerHandle& peer)
+{
   return bitfieldMan->hasMissingPiece(peer->getBitfield(),
   return bitfieldMan->hasMissingPiece(peer->getBitfield(),
 				      peer->getBitfieldLength());
 				      peer->getBitfieldLength());
 }
 }
 
 
-bool DefaultPieceStorage::isEndGame() {
+bool DefaultPieceStorage::isEndGame()
+{
   return bitfieldMan->countMissingBlock() <= endGamePieceNum;
   return bitfieldMan->countMissingBlock() <= endGamePieceNum;
 }
 }
 
 
-int32_t DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer) {
+int32_t DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer)
+{
   int32_t index = -1;
   int32_t index = -1;
   if(isEndGame()) {
   if(isEndGame()) {
     index = bitfieldMan->getMissingIndex(peer->getBitfield(),
     index = bitfieldMan->getMissingIndex(peer->getBitfield(),
@@ -84,7 +89,8 @@ int32_t DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer) {
   return index;
   return index;
 }
 }
 
 
-PieceHandle DefaultPieceStorage::checkOutPiece(int32_t index) {
+PieceHandle DefaultPieceStorage::checkOutPiece(int32_t index)
+{
   if(index == -1) {
   if(index == -1) {
     return 0;
     return 0;
   }
   }
@@ -104,7 +110,8 @@ PieceHandle DefaultPieceStorage::checkOutPiece(int32_t index) {
  * Newly instantiated piece is not added to usedPieces.
  * Newly instantiated piece is not added to usedPieces.
  * Because it is waste of memory and there is no chance to use them later.
  * Because it is waste of memory and there is no chance to use them later.
  */
  */
-PieceHandle DefaultPieceStorage::getPiece(int32_t index) {
+PieceHandle DefaultPieceStorage::getPiece(int32_t index)
+{
   if(0 <= index && index <= bitfieldMan->getMaxIndex()) {
   if(0 <= index && index <= bitfieldMan->getMaxIndex()) {
     PieceHandle piece = findUsedPiece(index);
     PieceHandle piece = findUsedPiece(index);
     if(piece.isNull()) {
     if(piece.isNull()) {
@@ -119,7 +126,8 @@ PieceHandle DefaultPieceStorage::getPiece(int32_t index) {
   }
   }
 }
 }
 
 
-void DefaultPieceStorage::addUsedPiece(const PieceHandle& piece) {
+void DefaultPieceStorage::addUsedPiece(const PieceHandle& piece)
+{
   usedPieces.push_back(piece);
   usedPieces.push_back(piece);
 }
 }
 
 
@@ -134,7 +142,8 @@ public:
   }
   }
 };
 };
 
 
-PieceHandle DefaultPieceStorage::findUsedPiece(int32_t index) const {
+PieceHandle DefaultPieceStorage::findUsedPiece(int32_t index) const
+{
   Pieces::const_iterator itr = find_if(usedPieces.begin(),
   Pieces::const_iterator itr = find_if(usedPieces.begin(),
 				       usedPieces.end(),
 				       usedPieces.end(),
 				       FindPiece(index));
 				       FindPiece(index));
@@ -145,12 +154,14 @@ PieceHandle DefaultPieceStorage::findUsedPiece(int32_t index) const {
   }
   }
 }
 }
 
 
-PieceHandle DefaultPieceStorage::getMissingPiece(const PeerHandle& peer) {
+PieceHandle DefaultPieceStorage::getMissingPiece(const PeerHandle& peer)
+{
   int32_t index = getMissingPieceIndex(peer);
   int32_t index = getMissingPieceIndex(peer);
   return checkOutPiece(index);
   return checkOutPiece(index);
 }
 }
 
 
-int32_t DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer) {
+int32_t DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer)
+{
   int32_t index = -1;
   int32_t index = -1;
   if(peer->isFastExtensionEnabled() && peer->countFastSet() > 0) {
   if(peer->isFastExtensionEnabled() && peer->countFastSet() > 0) {
     BitfieldMan tempBitfield(bitfieldMan->getBlockLength(),
     BitfieldMan tempBitfield(bitfieldMan->getBlockLength(),
@@ -172,12 +183,28 @@ int32_t DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer) {
   return index;
   return index;
 }
 }
 
 
-PieceHandle DefaultPieceStorage::getMissingFastPiece(const PeerHandle& peer) {
+PieceHandle DefaultPieceStorage::getMissingFastPiece(const PeerHandle& peer)
+{
   int32_t index = getMissingFastPieceIndex(peer);
   int32_t index = getMissingFastPieceIndex(peer);
   return checkOutPiece(index);
   return checkOutPiece(index);
 }
 }
 
 
-void DefaultPieceStorage::deleteUsedPiece(const PieceHandle& piece) {
+PieceHandle DefaultPieceStorage::getMissingPiece()
+{
+  return checkOutPiece(bitfieldMan->getSparseMissingUnusedIndex());
+}
+
+PieceHandle DefaultPieceStorage::getMissingPiece(int32_t index)
+{
+  if(hasPiece(index) || isPieceUsed(index)) {
+    return 0;
+  } else {
+    return checkOutPiece(index);
+  }
+}
+
+void DefaultPieceStorage::deleteUsedPiece(const PieceHandle& piece)
+{
   if(piece.isNull()) {
   if(piece.isNull()) {
     return;
     return;
   }
   }
@@ -187,7 +214,8 @@ void DefaultPieceStorage::deleteUsedPiece(const PieceHandle& piece) {
   }
   }
 }
 }
 
 
-void DefaultPieceStorage::reduceUsedPieces(int32_t delMax) {
+void DefaultPieceStorage::reduceUsedPieces(int32_t delMax)
+{
   int32_t toDelete = usedPieces.size()-delMax;
   int32_t toDelete = usedPieces.size()-delMax;
   if(toDelete <= 0) {
   if(toDelete <= 0) {
     return;
     return;
@@ -204,7 +232,8 @@ void DefaultPieceStorage::reduceUsedPieces(int32_t delMax) {
 }
 }
 
 
 int32_t DefaultPieceStorage::deleteUsedPiecesByFillRate(int32_t fillRate,
 int32_t DefaultPieceStorage::deleteUsedPiecesByFillRate(int32_t fillRate,
-							   int32_t toDelete) {
+							int32_t toDelete)
+{
   int32_t deleted = 0;
   int32_t deleted = 0;
   for(Pieces::iterator itr = usedPieces.begin();
   for(Pieces::iterator itr = usedPieces.begin();
       itr != usedPieces.end() && deleted < toDelete;) {
       itr != usedPieces.end() && deleted < toDelete;) {
@@ -224,7 +253,8 @@ int32_t DefaultPieceStorage::deleteUsedPiecesByFillRate(int32_t fillRate,
   return deleted;
   return deleted;
 }
 }
 
 
-void DefaultPieceStorage::completePiece(const PieceHandle& piece) {
+void DefaultPieceStorage::completePiece(const PieceHandle& piece)
+{
   if(piece.isNull()) {
   if(piece.isNull()) {
     return;
     return;
   }
   }
@@ -250,17 +280,20 @@ void DefaultPieceStorage::completePiece(const PieceHandle& piece) {
   }
   }
 }
 }
 
 
-bool DefaultPieceStorage::isSelectiveDownloadingMode() {
+bool DefaultPieceStorage::isSelectiveDownloadingMode()
+{
   return bitfieldMan->isFilterEnabled();
   return bitfieldMan->isFilterEnabled();
 }
 }
 
 
-void DefaultPieceStorage::finishSelectiveDownloadingMode() {
+void DefaultPieceStorage::finishSelectiveDownloadingMode()
+{
   bitfieldMan->clearFilter();
   bitfieldMan->clearFilter();
   diskAdaptor->addAllDownloadEntry();
   diskAdaptor->addAllDownloadEntry();
 }
 }
 
 
 // not unittested
 // not unittested
-void DefaultPieceStorage::cancelPiece(const PieceHandle& piece) {
+void DefaultPieceStorage::cancelPiece(const PieceHandle& piece)
+{
   if(piece.isNull()) {
   if(piece.isNull()) {
     return;
     return;
   }
   }
@@ -272,29 +305,40 @@ void DefaultPieceStorage::cancelPiece(const PieceHandle& piece) {
   }
   }
 }
 }
 
 
-bool DefaultPieceStorage::hasPiece(int32_t index) {
+bool DefaultPieceStorage::hasPiece(int32_t index)
+{
   return bitfieldMan->isBitSet(index);
   return bitfieldMan->isBitSet(index);
 }
 }
 
 
-int64_t DefaultPieceStorage::getTotalLength() {
+bool DefaultPieceStorage::isPieceUsed(int32_t index)
+{
+  return bitfieldMan->isUseBitSet(index);
+}
+
+int64_t DefaultPieceStorage::getTotalLength()
+{
   return bitfieldMan->getTotalLength();
   return bitfieldMan->getTotalLength();
 }
 }
 
 
-int64_t DefaultPieceStorage::getFilteredTotalLength() {
+int64_t DefaultPieceStorage::getFilteredTotalLength()
+{
   return bitfieldMan->getFilteredTotalLength();
   return bitfieldMan->getFilteredTotalLength();
 }
 }
 
 
-int64_t DefaultPieceStorage::getCompletedLength() {
+int64_t DefaultPieceStorage::getCompletedLength()
+{
   return bitfieldMan->getCompletedLength();
   return bitfieldMan->getCompletedLength();
 }
 }
 
 
-int64_t DefaultPieceStorage::getFilteredCompletedLength() {
+int64_t DefaultPieceStorage::getFilteredCompletedLength()
+{
   return bitfieldMan->getFilteredCompletedLength();
   return bitfieldMan->getFilteredCompletedLength();
 }
 }
 
 
 // not unittested
 // not unittested
-void DefaultPieceStorage::setFileFilter(const Strings& filePaths) {
-  if(btContext->getFileMode() != BtContext::MULTI || filePaths.empty()) {
+void DefaultPieceStorage::setFileFilter(const Strings& filePaths)
+{
+  if(downloadContext->getFileMode() != DownloadContext::MULTI || filePaths.empty()) {
     return;
     return;
   }
   }
   diskAdaptor->removeAllDownloadEntry();
   diskAdaptor->removeAllDownloadEntry();
@@ -309,7 +353,8 @@ void DefaultPieceStorage::setFileFilter(const Strings& filePaths) {
   bitfieldMan->enableFilter();
   bitfieldMan->enableFilter();
 }
 }
 
 
-void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes) {
+void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes)
+{
   Strings filePaths;
   Strings filePaths;
   const FileEntries& entries = diskAdaptor->getFileEntries();
   const FileEntries& entries = diskAdaptor->getFileEntries();
   for(int32_t i = 0; i < (int32_t)entries.size(); i++) {
   for(int32_t i = 0; i < (int32_t)entries.size(); i++) {
@@ -322,66 +367,77 @@ void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes) {
 }
 }
 
 
 // not unittested
 // not unittested
-void DefaultPieceStorage::clearFileFilter() {
+void DefaultPieceStorage::clearFileFilter()
+{
   bitfieldMan->clearFilter();
   bitfieldMan->clearFilter();
   diskAdaptor->addAllDownloadEntry();
   diskAdaptor->addAllDownloadEntry();
 }
 }
 
 
 // not unittested
 // not unittested
-bool DefaultPieceStorage::downloadFinished() {
+bool DefaultPieceStorage::downloadFinished()
+{
   return bitfieldMan->isFilteredAllBitSet();
   return bitfieldMan->isFilteredAllBitSet();
 }
 }
 
 
 // not unittested
 // not unittested
-bool DefaultPieceStorage::allDownloadFinished() {
+bool DefaultPieceStorage::allDownloadFinished()
+{
   return bitfieldMan->isAllBitSet();
   return bitfieldMan->isAllBitSet();
 }
 }
 
 
 // not unittested
 // not unittested
-void DefaultPieceStorage::initStorage() {
-  if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) {
-    if(btContext->getFileMode() == BtContext::SINGLE) {
-      DefaultDiskWriterHandle writer = DefaultDiskWriter::createNewDiskWriter(option);
-      DirectDiskAdaptorHandle directDiskAdaptor = new DirectDiskAdaptor();
-      directDiskAdaptor->setDiskWriter(writer);
-      directDiskAdaptor->setTotalLength(btContext->getTotalLength());
-      this->diskAdaptor = directDiskAdaptor;
-    } else {
+void DefaultPieceStorage::initStorage()
+{
+  if(downloadContext->getFileMode() == DownloadContext::SINGLE) {
+    logger->debug("Instantiating DirectDiskAdaptor");
+    DiskWriterHandle writer = _diskWriterFactory->newDiskWriter();
+    DirectDiskAdaptorHandle directDiskAdaptor = new DirectDiskAdaptor();
+    directDiskAdaptor->setDiskWriter(writer);
+    directDiskAdaptor->setTotalLength(downloadContext->getTotalLength());
+    this->diskAdaptor = directDiskAdaptor;
+  } else {
+    // file mode == DownloadContext::MULTI
+    if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) {
+      logger->debug("Instantiating MultiDiskAdaptor");
       MultiDiskAdaptorHandle multiDiskAdaptor = new MultiDiskAdaptor();
       MultiDiskAdaptorHandle multiDiskAdaptor = new MultiDiskAdaptor();
-      multiDiskAdaptor->setPieceLength(btContext->getPieceLength());
-      multiDiskAdaptor->setTopDir(btContext->getName());
+      multiDiskAdaptor->setPieceLength(downloadContext->getPieceLength());
+      multiDiskAdaptor->setTopDir(downloadContext->getName());
       multiDiskAdaptor->setOption(option);
       multiDiskAdaptor->setOption(option);
       this->diskAdaptor = multiDiskAdaptor;
       this->diskAdaptor = multiDiskAdaptor;
+    } else {
+      logger->debug("Instantiating CopyDiskAdaptor");
+      DiskWriterHandle writer = _diskWriterFactory->newDiskWriter();
+      CopyDiskAdaptorHandle copyDiskAdaptor = new CopyDiskAdaptor();
+      copyDiskAdaptor->setDiskWriter(writer);
+      copyDiskAdaptor->setTempFilename(downloadContext->getName()+".a2tmp");
+      copyDiskAdaptor->setTotalLength(downloadContext->getTotalLength());
+      if(downloadContext->getFileMode() == DownloadContext::MULTI) {
+	copyDiskAdaptor->setTopDir(downloadContext->getName());
+      }
+      this->diskAdaptor = copyDiskAdaptor;
     }
     }
-  } else {
-    DefaultDiskWriterHandle writer = DefaultDiskWriter::createNewDiskWriter(option);
-    CopyDiskAdaptorHandle copyDiskAdaptor = new CopyDiskAdaptor();
-    copyDiskAdaptor->setDiskWriter(writer);
-    copyDiskAdaptor->setTempFilename(btContext->getName()+".a2tmp");
-    copyDiskAdaptor->setTotalLength(btContext->getTotalLength());
-    if(btContext->getFileMode() == BtContext::MULTI) {
-      copyDiskAdaptor->setTopDir(btContext->getName());
-    }
-    this->diskAdaptor = copyDiskAdaptor;
-  }
-  string storeDir = option->get(PREF_DIR);
-  if(storeDir == "") {
-    storeDir = ".";
   }
   }
+  string storeDir = downloadContext->getDir();//option->get(PREF_DIR);
+//   if(storeDir == "") {
+//     storeDir = ".";
+//   }
   diskAdaptor->setStoreDir(storeDir);
   diskAdaptor->setStoreDir(storeDir);
-  diskAdaptor->setFileEntries(btContext->getFileEntries());
+  diskAdaptor->setFileEntries(downloadContext->getFileEntries());
 }
 }
 
 
 void DefaultPieceStorage::setBitfield(const unsigned char* bitfield,
 void DefaultPieceStorage::setBitfield(const unsigned char* bitfield,
-				      int32_t bitfieldLength) {
+				      int32_t bitfieldLength)
+{
   bitfieldMan->setBitfield(bitfield, bitfieldLength);
   bitfieldMan->setBitfield(bitfield, bitfieldLength);
 }
 }
   
   
-int32_t DefaultPieceStorage::getBitfieldLength() {
+int32_t DefaultPieceStorage::getBitfieldLength()
+{
   return bitfieldMan->getBitfieldLength();
   return bitfieldMan->getBitfieldLength();
 }
 }
 
 
-const unsigned char* DefaultPieceStorage::getBitfield() {
+const unsigned char* DefaultPieceStorage::getBitfield()
+{
   return bitfieldMan->getBitfield();
   return bitfieldMan->getBitfield();
 }
 }
 
 
@@ -389,17 +445,20 @@ DiskAdaptorHandle DefaultPieceStorage::getDiskAdaptor() {
   return diskAdaptor;
   return diskAdaptor;
 }
 }
 
 
-int32_t DefaultPieceStorage::getPieceLength(int32_t index) {
+int32_t DefaultPieceStorage::getPieceLength(int32_t index)
+{
   return bitfieldMan->getBlockLength(index);
   return bitfieldMan->getBlockLength(index);
 }
 }
 
 
-void DefaultPieceStorage::advertisePiece(int32_t cuid, int32_t index) {
+void DefaultPieceStorage::advertisePiece(int32_t cuid, int32_t index)
+{
   HaveEntry entry(cuid, index);
   HaveEntry entry(cuid, index);
   haves.push_front(entry);
   haves.push_front(entry);
 }
 }
 
 
 Integers DefaultPieceStorage::getAdvertisedPieceIndexes(int32_t myCuid,
 Integers DefaultPieceStorage::getAdvertisedPieceIndexes(int32_t myCuid,
-							const Time& lastCheckTime) {
+							const Time& lastCheckTime)
+{
   Integers indexes;
   Integers indexes;
   for(Haves::const_iterator itr = haves.begin(); itr != haves.end(); itr++) {
   for(Haves::const_iterator itr = haves.begin(); itr != haves.end(); itr++) {
     const Haves::value_type& have = *itr;
     const Haves::value_type& have = *itr;
@@ -430,7 +489,8 @@ public:
   }
   }
 };
 };
   
   
-void DefaultPieceStorage::removeAdvertisedPiece(int32_t elapsed) {
+void DefaultPieceStorage::removeAdvertisedPiece(int32_t elapsed)
+{
   Haves::iterator itr =
   Haves::iterator itr =
     find_if(haves.begin(), haves.end(), FindElapsedHave(elapsed));
     find_if(haves.begin(), haves.end(), FindElapsedHave(elapsed));
   if(itr != haves.end()) {
   if(itr != haves.end()) {
@@ -444,19 +504,33 @@ void DefaultPieceStorage::markAllPiecesDone()
   bitfieldMan->setAllBit();
   bitfieldMan->setAllBit();
 }
 }
 
 
-void DefaultPieceStorage::checkIntegrity()
+void DefaultPieceStorage::markPiecesDone(int64_t length)
 {
 {
-  logger->notice(MSG_VALIDATING_FILE,
-		 diskAdaptor->getFilePath().c_str());
-  ChunkChecksumHandle chunkChecksum = new ChunkChecksum("sha1",
-							btContext->getPieceHashes(),
-							btContext->getPieceLength());
-  IteratableChunkChecksumValidatorHandle iv = new IteratableChunkChecksumValidator();
-  iv->setDiskWriter(new DiskAdaptorWriter(diskAdaptor));
-  iv->setBitfield(bitfieldMan);
-  iv->setChunkChecksum(chunkChecksum);
+  // TODO implement this
+  abort();
+}
 
 
-  ChunkChecksumValidator v(iv);
-  v.setFileAllocationMonitor(FileAllocationMonitorFactory::getFactory()->createNewMonitor());
-  v.validate();
+void DefaultPieceStorage::markPieceMissing(int32_t index)
+{
+  bitfieldMan->unsetBit(index);
+}
+
+void DefaultPieceStorage::addInFlightPiece(const Pieces& pieces)
+{
+  copy(pieces.begin(), pieces.end(), back_inserter(usedPieces));
+}
+
+int32_t DefaultPieceStorage::countInFlightPiece()
+{
+  return usedPieces.size();
+}
+
+Pieces DefaultPieceStorage::getInFlightPieces()
+{
+  return usedPieces;
+}
+
+void DefaultPieceStorage::setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory)
+{
+  _diskWriterFactory = diskWriterFactory;
 }
 }

+ 30 - 11
src/DefaultPieceStorage.h

@@ -36,13 +36,15 @@
 #define _D_DEFAULT_PIECE_STORAGE_H_
 #define _D_DEFAULT_PIECE_STORAGE_H_
 
 
 #include "PieceStorage.h"
 #include "PieceStorage.h"
-#include "BtContext.h"
-#include "DiskAdaptor.h"
-#include "BitfieldMan.h"
-#include "Logger.h"
-#include "Option.h"
-#include "Piece.h"
-#include "FileAllocator.h"
+
+class DownloadContext;
+extern typedef SharedHandle<DownloadContext> DownloadContextHandle;
+class BitfieldMan;
+class Logger;
+class Option;
+extern typedef deque<PieceHandle> Pieces;
+class DiskWriterFactory;
+extern typedef SharedHandle<DiskWriterFactory> DiskWriterFactoryHandle;
 
 
 #define END_GAME_PIECE_NUM 20
 #define END_GAME_PIECE_NUM 20
 
 
@@ -67,15 +69,15 @@ typedef deque<HaveEntry> Haves;
 
 
 class DefaultPieceStorage : public PieceStorage {
 class DefaultPieceStorage : public PieceStorage {
 private:
 private:
-  BtContextHandle btContext;
+  DownloadContextHandle downloadContext;
   BitfieldMan* bitfieldMan;
   BitfieldMan* bitfieldMan;
   DiskAdaptorHandle diskAdaptor;
   DiskAdaptorHandle diskAdaptor;
+  DiskWriterFactoryHandle _diskWriterFactory;
   Pieces usedPieces;
   Pieces usedPieces;
   int32_t endGamePieceNum;
   int32_t endGamePieceNum;
   Logger* logger;
   Logger* logger;
   const Option* option;
   const Option* option;
   Haves haves;
   Haves haves;
-  FileAllocatorHandle createFileAllocator();
 
 
   int32_t getMissingPieceIndex(const PeerHandle& peer);
   int32_t getMissingPieceIndex(const PeerHandle& peer);
   int32_t getMissingFastPieceIndex(const PeerHandle& peer);
   int32_t getMissingFastPieceIndex(const PeerHandle& peer);
@@ -85,7 +87,7 @@ private:
   void deleteUsedPiece(const PieceHandle& piece);
   void deleteUsedPiece(const PieceHandle& piece);
   PieceHandle findUsedPiece(int32_t index) const;
   PieceHandle findUsedPiece(int32_t index) const;
 public:
 public:
-  DefaultPieceStorage(BtContextHandle btContext, const Option* option);
+  DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option);
   virtual ~DefaultPieceStorage();
   virtual ~DefaultPieceStorage();
 
 
   virtual bool hasMissingPiece(const PeerHandle& peer);
   virtual bool hasMissingPiece(const PeerHandle& peer);
@@ -94,6 +96,10 @@ public:
 
 
   virtual PieceHandle getMissingFastPiece(const PeerHandle& peer);
   virtual PieceHandle getMissingFastPiece(const PeerHandle& peer);
 
 
+  virtual PieceHandle getMissingPiece();
+
+  virtual PieceHandle getMissingPiece(int32_t index);
+
   virtual PieceHandle getPiece(int32_t index);
   virtual PieceHandle getPiece(int32_t index);
 
 
   virtual void completePiece(const PieceHandle& piece);
   virtual void completePiece(const PieceHandle& piece);
@@ -102,6 +108,8 @@ public:
 
 
   virtual bool hasPiece(int32_t index);
   virtual bool hasPiece(int32_t index);
 
 
+  virtual bool isPieceUsed(int32_t index);
+
   virtual int64_t getTotalLength();
   virtual int64_t getTotalLength();
 
 
   virtual int64_t getFilteredTotalLength();
   virtual int64_t getFilteredTotalLength();
@@ -156,13 +164,24 @@ public:
 
 
   virtual void markAllPiecesDone();
   virtual void markAllPiecesDone();
 
 
-  virtual void checkIntegrity();
+  virtual void markPiecesDone(int64_t length);
+
+  virtual void markPieceMissing(int32_t index);
+
+  virtual void addInFlightPiece(const Pieces& pieces);
+
+  virtual int32_t countInFlightPiece();
+
+  virtual Pieces getInFlightPieces();
 
 
   /**
   /**
    * This method is made private for test purpose only.
    * This method is made private for test purpose only.
    */
    */
   void addUsedPiece(const PieceHandle& piece);
   void addUsedPiece(const PieceHandle& piece);
 
 
+  void setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory);
 };
 };
 
 
+typedef SharedHandle<DefaultPieceStorage> DefaultPieceStorageHandle;
+
 #endif // _D_DEFAULT_PIECE_STORAGE_H_
 #endif // _D_DEFAULT_PIECE_STORAGE_H_

+ 6 - 5
src/DefaultSegmentManFactory.cc

@@ -36,13 +36,14 @@
 #include "prefs.h"
 #include "prefs.h"
 #include "DefaultDiskWriter.h"
 #include "DefaultDiskWriter.h"
 
 
-SegmentManHandle DefaultSegmentManFactory::createNewInstance()
+SegmentManHandle DefaultSegmentManFactory::createNewInstance(const DownloadContextHandle& dctx,
+							     const PieceStorageHandle& ps)
 {
 {
-  SegmentManHandle segmentMan = new SegmentMan();
-  segmentMan->diskWriter = new DefaultDiskWriter();
-  segmentMan->dir = _option->get(PREF_DIR);
+  SegmentManHandle segmentMan = new SegmentMan(_option, dctx, ps);
+  //segmentMan->diskWriter = new DefaultDiskWriter();
+  //segmentMan->dir = _option->get(PREF_DIR);
   // TODO disable this in multi-simultaneous download mode.
   // TODO disable this in multi-simultaneous download mode.
   //segmentMan->ufilename = _option->get(PREF_OUT);
   //segmentMan->ufilename = _option->get(PREF_OUT);
-  segmentMan->option = _option;
+  //segmentMan->option = _option;
   return segmentMan;
   return segmentMan;
 }
 }

+ 2 - 1
src/DefaultSegmentManFactory.h

@@ -43,7 +43,8 @@ public:
 
 
   virtual ~DefaultSegmentManFactory() {}
   virtual ~DefaultSegmentManFactory() {}
 
 
-  virtual SegmentManHandle createNewInstance();
+  virtual SegmentManHandle createNewInstance(const DownloadContextHandle& dc,
+					     const PieceStorageHandle& ps);
 };
 };
 
 
 typedef SharedHandle<DefaultSegmentManFactory> DefaultSegmentManFactoryHandle;
 typedef SharedHandle<DefaultSegmentManFactory> DefaultSegmentManFactoryHandle;

+ 14 - 2
src/FileAllocationMonitor.cc → src/Dependency.h

@@ -32,6 +32,18 @@
  * files in the program, then also delete it here.
  * files in the program, then also delete it here.
  */
  */
 /* copyright --> */
 /* copyright --> */
-#include "FileAllocationMonitor.h"
+#ifndef _D_DEPENDENCY_H_
+#define _D_DEPENDENCY_H_
 
 
-FileAllocationMonitorFactoryHandle FileAllocationMonitorFactory::factory = 0;
+#include "common.h"
+
+class Dependency {
+public:
+  virtual ~Dependency() {}
+
+  virtual bool resolve() = 0;
+};
+
+typedef SharedHandle<Dependency> DependencyHandle;
+
+#endif // _D_DEPENDENCY_H_

+ 5 - 2
src/DirectDiskAdaptor.cc

@@ -34,11 +34,14 @@
 /* copyright --> */
 /* copyright --> */
 #include "DirectDiskAdaptor.h"
 #include "DirectDiskAdaptor.h"
 
 
-string DirectDiskAdaptor::getFilePath() {
+string DirectDiskAdaptor::getFilePath()
+{
   return storeDir+"/"+fileEntries.front()->getPath();
   return storeDir+"/"+fileEntries.front()->getPath();
 }
 }
 
 
-void DirectDiskAdaptor::onDownloadComplete() {
+void DirectDiskAdaptor::onDownloadComplete()
+  throw(DlAbortEx*)
+{
   closeFile();
   closeFile();
   openFile();
   openFile();
 }
 }

+ 2 - 1
src/DirectDiskAdaptor.h

@@ -36,6 +36,7 @@
 #define _D_DIRECT_DISK_ADAPTOR_H_
 #define _D_DIRECT_DISK_ADAPTOR_H_
 
 
 #include "AbstractSingleDiskAdaptor.h"
 #include "AbstractSingleDiskAdaptor.h"
+#include "DlAbortEx.h"
 
 
 class DirectDiskAdaptor : public AbstractSingleDiskAdaptor {
 class DirectDiskAdaptor : public AbstractSingleDiskAdaptor {
 public:
 public:
@@ -44,7 +45,7 @@ public:
 
 
   virtual string getFilePath();
   virtual string getFilePath();
 
 
-  virtual void onDownloadComplete();
+  virtual void onDownloadComplete() throw(DlAbortEx*);
 };
 };
 
 
 typedef SharedHandle<DirectDiskAdaptor> DirectDiskAdaptorHandle;
 typedef SharedHandle<DirectDiskAdaptor> DirectDiskAdaptorHandle;

+ 11 - 6
src/DiskAdaptor.cc

@@ -33,7 +33,6 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "DiskAdaptor.h"
 #include "DiskAdaptor.h"
-#include "DlAbortEx.h"
 #include "LogFactory.h"
 #include "LogFactory.h"
 #include "message.h"
 #include "message.h"
 
 
@@ -41,7 +40,9 @@ DiskAdaptor::DiskAdaptor():logger(LogFactory::getInstance()) {}
 
 
 DiskAdaptor::~DiskAdaptor() {}
 DiskAdaptor::~DiskAdaptor() {}
 
 
-FileEntryHandle DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) const {
+FileEntryHandle DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) const
+  throw(DlAbortEx*)
+{
   for(FileEntries::const_iterator itr = fileEntries.begin();
   for(FileEntries::const_iterator itr = fileEntries.begin();
       itr != fileEntries.end(); itr++) {
       itr != fileEntries.end(); itr++) {
     if((*itr)->getPath() == fileEntryPath) {
     if((*itr)->getPath() == fileEntryPath) {
@@ -51,7 +52,8 @@ FileEntryHandle DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) c
   throw new DlAbortEx(EX_NO_SUCH_FILE_ENTRY, fileEntryPath.c_str());
   throw new DlAbortEx(EX_NO_SUCH_FILE_ENTRY, fileEntryPath.c_str());
 }
 }
 
 
-bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath) {
+bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath)
+{
   for(FileEntries::iterator itr = fileEntries.begin();
   for(FileEntries::iterator itr = fileEntries.begin();
       itr != fileEntries.end(); itr++) {
       itr != fileEntries.end(); itr++) {
     if((*itr)->getPath() == fileEntryPath) {
     if((*itr)->getPath() == fileEntryPath) {
@@ -62,7 +64,8 @@ bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath) {
   return false;
   return false;
 }
 }
 
 
-bool DiskAdaptor::addDownloadEntry(int index) {
+bool DiskAdaptor::addDownloadEntry(int index)
+{
   if(fileEntries.size() <= (unsigned int)index) {
   if(fileEntries.size() <= (unsigned int)index) {
     return false;
     return false;
   }
   }
@@ -70,14 +73,16 @@ bool DiskAdaptor::addDownloadEntry(int index) {
   return true;
   return true;
 }
 }
 
 
-void DiskAdaptor::addAllDownloadEntry() {
+void DiskAdaptor::addAllDownloadEntry()
+{
   for(FileEntries::iterator itr = fileEntries.begin();
   for(FileEntries::iterator itr = fileEntries.begin();
       itr != fileEntries.end(); itr++) {
       itr != fileEntries.end(); itr++) {
     (*itr)->setRequested(true);
     (*itr)->setRequested(true);
   }
   }
 }
 }
 
 
-void DiskAdaptor::removeAllDownloadEntry() {
+void DiskAdaptor::removeAllDownloadEntry()
+{
   for(FileEntries::iterator itr = fileEntries.begin();
   for(FileEntries::iterator itr = fileEntries.begin();
       itr != fileEntries.end(); itr++) {
       itr != fileEntries.end(); itr++) {
     (*itr)->setRequested(false);
     (*itr)->setRequested(false);

+ 11 - 7
src/DiskAdaptor.h

@@ -35,11 +35,13 @@
 #ifndef _D_DISK_ADAPTOR_H_
 #ifndef _D_DISK_ADAPTOR_H_
 #define _D_DISK_ADAPTOR_H_
 #define _D_DISK_ADAPTOR_H_
 
 
-#include "common.h"
+#include "BinaryStream.h"
 #include "FileEntry.h"
 #include "FileEntry.h"
 #include "Logger.h"
 #include "Logger.h"
+#include "FileAllocationIterator.h"
+#include "DlAbortEx.h"
 
 
-class DiskAdaptor {
+class DiskAdaptor:public BinaryStream {
 protected:
 protected:
   string storeDir;
   string storeDir;
   FileEntries fileEntries;
   FileEntries fileEntries;
@@ -56,10 +58,6 @@ public:
 
 
   virtual void initAndOpenFile() = 0;
   virtual void initAndOpenFile() = 0;
 
 
-  virtual void writeData(const unsigned char* data, int32_t len, int64_t offset) = 0;
-
-  virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) = 0;
-
   virtual void onDownloadComplete() = 0;  
   virtual void onDownloadComplete() = 0;  
 
 
   virtual bool fileExists() = 0;
   virtual bool fileExists() = 0;
@@ -68,11 +66,15 @@ public:
 
 
   virtual int64_t size() const = 0;
   virtual int64_t size() const = 0;
 
 
+  // optional behavior
+  virtual void truncate(int64_t length) {}
+
   void setFileEntries(const FileEntries& fileEntries) {
   void setFileEntries(const FileEntries& fileEntries) {
     this->fileEntries = fileEntries;
     this->fileEntries = fileEntries;
   }
   }
 
 
-  FileEntryHandle getFileEntryFromPath(const string& fileEntryPath) const;
+  FileEntryHandle
+  getFileEntryFromPath(const string& fileEntryPath) const throw(DlAbortEx*);
 
 
   const FileEntries& getFileEntries() const { return fileEntries; }
   const FileEntries& getFileEntries() const { return fileEntries; }
 
 
@@ -87,6 +89,8 @@ public:
   void setStoreDir(const string& storeDir) { this->storeDir = storeDir; }
   void setStoreDir(const string& storeDir) { this->storeDir = storeDir; }
 
 
   const string& getStoreDir() const { return this->storeDir; }
   const string& getStoreDir() const { return this->storeDir; }
+
+  virtual FileAllocationIteratorHandle fileAllocationIterator() = 0;
 };
 };
 
 
 typedef SharedHandle<DiskAdaptor> DiskAdaptorHandle;
 typedef SharedHandle<DiskAdaptor> DiskAdaptorHandle;

+ 5 - 25
src/DiskWriter.h

@@ -35,15 +35,14 @@
 #ifndef _D_DISK_WRITER_H_
 #ifndef _D_DISK_WRITER_H_
 #define _D_DISK_WRITER_H_
 #define _D_DISK_WRITER_H_
 
 
-#include "common.h"
-
-using namespace std;
+#include "BinaryStream.h"
+#include "DlAbortEx.h"
 
 
 /**
 /**
  * Interface for writing to a binary stream of bytes.
  * Interface for writing to a binary stream of bytes.
  *
  *
  */
  */
-class DiskWriter {
+class DiskWriter:public BinaryStream {
 public:
 public:
   virtual ~DiskWriter() {}
   virtual ~DiskWriter() {}
   /**
   /**
@@ -51,13 +50,14 @@ public:
    * If the file exists, then it is truncated to 0 length.
    * If the file exists, then it is truncated to 0 length.
    * @param filename the file name to be opened.
    * @param filename the file name to be opened.
    */
    */
-  virtual void initAndOpenFile(const string& filename, int64_t totalLength = 0) = 0;
+  virtual void initAndOpenFile(const string& filename, int64_t totalLength = 0)  = 0;
   
   
   virtual void openFile(const string& filename, int64_t totalLength = 0) = 0;
   virtual void openFile(const string& filename, int64_t totalLength = 0) = 0;
 
 
   /**
   /**
    * Closes this output stream.
    * Closes this output stream.
    */
    */
+  // TODO we have to examine the return value of close()
   virtual void closeFile() = 0;
   virtual void closeFile() = 0;
 
 
   /**
   /**
@@ -68,26 +68,6 @@ public:
    */
    */
   virtual void openExistingFile(const string& filename, int64_t totalLength = 0) = 0;
   virtual void openExistingFile(const string& filename, int64_t totalLength = 0) = 0;
 
 
-  /*
-   * Writes len bytes from data to this binary stream at offset position.
-   * In case where offset position is not concerned(just write data
-   * sequencially, for example), those subclasses can ignore the offset value.
-   *
-   * @param data the data
-   * @param len the number of bytes to write
-   * @param position the offset of this binary stream
-   */
-  virtual void writeData(const char* data, int32_t len, int64_t position = 0) = 0;
-  virtual void writeData(const unsigned char* data, int32_t len, int64_t position = 0)
-  {
-    writeData((const char*)data, len, position);
-  }
-
-  virtual int32_t readData(char* data, int32_t len, int64_t position) = 0;
-  virtual int32_t readData(unsigned char* data, int32_t len, int64_t position) {
-    return readData((char*)data, len, position);
-  }
-
   virtual void truncate(int64_t length) = 0;
   virtual void truncate(int64_t length) = 0;
 
 
   // Returns file length
   // Returns file length

+ 9 - 10
src/GlowFileAllocator.h → src/DiskWriterFactory.h

@@ -32,20 +32,19 @@
  * files in the program, then also delete it here.
  * files in the program, then also delete it here.
  */
  */
 /* copyright --> */
 /* copyright --> */
-#ifndef _D_GLOW_FILE_ALLOCATOR_H_
-#define _D_GLOW_FILE_ALLOCATOR_H_
+#ifndef _D_DISK_WRITER_FACTORY_H_
+#define _D_DISK_WRITER_FACTORY_H_
 
 
-#include "FileAllocator.h"
+#include "common.h"
+#include "DiskWriter.h"
 
 
-class GlowFileAllocator : public FileAllocator {
+class DiskWriterFactory {
 public:
 public:
-  GlowFileAllocator() {}
+  virtual ~DiskWriterFactory() {}
 
 
-  virtual ~GlowFileAllocator() {}
-
-  virtual void allocate(int fd, int64_t totalLength);
+  virtual DiskWriterHandle newDiskWriter() = 0;
 };
 };
 
 
-typedef SharedHandle<GlowFileAllocator> GlowFileAllocatorHandle;
+typedef SharedHandle<DiskWriterFactory> DiskWriterFactoryHandle;
 
 
-#endif // _D_GLOW_FILE_ALLOCATOR_H_
+#endif // _D_DISK_WRITER_FACTORY_H_

+ 45 - 16
src/DownloadCommand.cc

@@ -33,16 +33,20 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "DownloadCommand.h"
 #include "DownloadCommand.h"
+#include "SegmentMan.h"
+#include "PeerStat.h"
+#include "TransferEncoding.h"
+#include "DownloadContext.h"
 #include "Util.h"
 #include "Util.h"
 #include "DlRetryEx.h"
 #include "DlRetryEx.h"
 #include "DlAbortEx.h"
 #include "DlAbortEx.h"
-#include "HttpInitiateConnectionCommand.h"
 #include "InitiateConnectionCommandFactory.h"
 #include "InitiateConnectionCommandFactory.h"
 #include "message.h"
 #include "message.h"
 #include "prefs.h"
 #include "prefs.h"
-#ifdef ENABLE_MESSAGE_DIGEST
-# include "ChecksumCommand.h"
-#endif // ENABLE_MESSAGE_DIGEST
+#include "DiskAdaptor.h"
+#include "Segment.h"
+#include "PieceStorage.h"
+#include "Option.h"
 #include <stdlib.h>
 #include <stdlib.h>
 
 
 DownloadCommand::DownloadCommand(int cuid,
 DownloadCommand::DownloadCommand(int cuid,
@@ -80,17 +84,23 @@ bool DownloadCommand::executeInternal() {
   socket->readData(buf, bufSize);
   socket->readData(buf, bufSize);
 
 
   if(transferDecoder.isNull()) {
   if(transferDecoder.isNull()) {
-    _requestGroup->getSegmentMan()->diskWriter->writeData(buf, bufSize,
-							  segment->getPositionToWrite());
-    segment->writtenLength += bufSize;
+    _requestGroup->getPieceStorage()->getDiskAdaptor()->writeData((const unsigned char*)buf, bufSize,
+								segment->getPositionToWrite());
+    //logger->debug("bufSize = %d, posToWrite = %lld", bufSize, segment->getPositionToWrite());
+    segment->updateWrittenLength(bufSize);
+    //logger->debug("overflow length = %d, next posToWrite = %lld", segment->getOverflowLength(), segment->getPositionToWrite());
+    //logger->debug("%s", Util::toHex(segment->getPiece()->getBitfield(),
+    //segment->getPiece()->getBitfieldLength()).c_str());
+    //segment->writtenLength += bufSize;
     peerStat->updateDownloadLength(bufSize);
     peerStat->updateDownloadLength(bufSize);
   } else {
   } else {
     int32_t infbufSize = 16*1024;
     int32_t infbufSize = 16*1024;
     char infbuf[infbufSize];
     char infbuf[infbufSize];
     transferDecoder->inflate(infbuf, infbufSize, buf, bufSize);
     transferDecoder->inflate(infbuf, infbufSize, buf, bufSize);
-    _requestGroup->getSegmentMan()->diskWriter->writeData(infbuf, infbufSize,
-							  segment->getPositionToWrite());
-    segment->writtenLength += infbufSize;
+    _requestGroup->getPieceStorage()->getDiskAdaptor()->writeData((const unsigned char*)infbuf, infbufSize,
+								segment->getPositionToWrite());
+    segment->updateWrittenLength(infbufSize);
+    //segment->writtenLength += infbufSize;
     peerStat->updateDownloadLength(infbufSize);
     peerStat->updateDownloadLength(infbufSize);
   }
   }
   // calculate downloading speed
   // calculate downloading speed
@@ -103,7 +113,7 @@ bool DownloadCommand::executeInternal() {
 			  req->getHost().c_str());
 			  req->getHost().c_str());
     }
     }
   }
   }
-  if(_requestGroup->getSegmentMan()->totalSize != 0 && bufSize == 0) {
+  if(_requestGroup->getTotalLength() != 0 && bufSize == 0) {
     throw new DlRetryEx(EX_GOT_EOF);
     throw new DlRetryEx(EX_GOT_EOF);
   }
   }
   if(!transferDecoder.isNull() && transferDecoder->finished()
   if(!transferDecoder.isNull() && transferDecoder->finished()
@@ -112,11 +122,22 @@ bool DownloadCommand::executeInternal() {
     if(!transferDecoder.isNull()) transferDecoder->end();
     if(!transferDecoder.isNull()) transferDecoder->end();
     logger->info(MSG_SEGMENT_DOWNLOAD_COMPLETED, cuid);
     logger->info(MSG_SEGMENT_DOWNLOAD_COMPLETED, cuid);
     _requestGroup->getSegmentMan()->completeSegment(cuid, segment);
     _requestGroup->getSegmentMan()->completeSegment(cuid, segment);
+    // TODO According to the current plan, checksum is held by DownloadContext.
+#ifdef ENABLE_MESSAGE_DIGEST
+    if(e->option->get(PREF_REALTIME_CHUNK_CHECKSUM) == V_TRUE) {
+      string pieceHash = _requestGroup->getDownloadContext()->getPieceHash(segment->getIndex());
+      if(!pieceHash.empty()) {
+	_requestGroup->getSegmentMan()->validatePieceHash(segment, pieceHash);
+      }
+    }
+#endif // ENABLE_MESSAGE_DIGEST
+    /*
 #ifdef ENABLE_MESSAGE_DIGEST
 #ifdef ENABLE_MESSAGE_DIGEST
     if(e->option->get(PREF_REALTIME_CHUNK_CHECKSUM) == V_TRUE) {
     if(e->option->get(PREF_REALTIME_CHUNK_CHECKSUM) == V_TRUE) {
       _requestGroup->getSegmentMan()->tryChunkChecksumValidation(segment, _requestGroup->getChunkChecksum());
       _requestGroup->getSegmentMan()->tryChunkChecksumValidation(segment, _requestGroup->getChunkChecksum());
     }
     }
 #endif // ENABLE_MESSAGE_DIGEST
 #endif // ENABLE_MESSAGE_DIGEST
+    */
     // this unit is going to download another segment.
     // this unit is going to download another segment.
     return prepareForNextSegment();
     return prepareForNextSegment();
   } else {
   } else {
@@ -127,7 +148,9 @@ bool DownloadCommand::executeInternal() {
 }
 }
 
 
 bool DownloadCommand::prepareForNextSegment() {
 bool DownloadCommand::prepareForNextSegment() {
-  if(_requestGroup->getSegmentMan()->finished()) {
+  if(_requestGroup->downloadFinished()) {
+    // TODO According to the current plan, checksum is held by DownloadContext.
+    /*
 #ifdef ENABLE_MESSAGE_DIGEST
 #ifdef ENABLE_MESSAGE_DIGEST
     if(!_requestGroup->getChecksum().isNull() &&
     if(!_requestGroup->getChecksum().isNull() &&
        !_requestGroup->getChecksum()->isEmpty()) {
        !_requestGroup->getChecksum()->isEmpty()) {
@@ -136,6 +159,7 @@ bool DownloadCommand::prepareForNextSegment() {
       e->commands.push_back(command);
       e->commands.push_back(command);
     }
     }
 #endif // ENABLE_MESSAGE_DIGEST
 #endif // ENABLE_MESSAGE_DIGEST
+    */
     return true;
     return true;
   } else {
   } else {
     // Merge segment with next segment, if segment.index+1 == nextSegment.index
     // Merge segment with next segment, if segment.index+1 == nextSegment.index
@@ -143,15 +167,15 @@ bool DownloadCommand::prepareForNextSegment() {
     while(1) {
     while(1) {
       SegmentHandle nextSegment =
       SegmentHandle nextSegment =
 	_requestGroup->getSegmentMan()->getSegment(cuid,
 	_requestGroup->getSegmentMan()->getSegment(cuid,
-						   tempSegment->index+1);
+						   tempSegment->getIndex()+1);
       if(nextSegment.isNull()) {
       if(nextSegment.isNull()) {
 	break;
 	break;
       } else {
       } else {
-	if(nextSegment->writtenLength > 0) {
+	if(nextSegment->getWrittenLength() > 0) {
 	  return prepareForRetry(0);
 	  return prepareForRetry(0);
 	}
 	}
-	nextSegment->writtenLength =
-	  tempSegment->writtenLength-tempSegment->length;
+	nextSegment->updateWrittenLength(tempSegment->getOverflowLength());
+	//tempSegment->writtenLength-tempSegment->length;
 	if(nextSegment->complete()) {
 	if(nextSegment->complete()) {
 	  _requestGroup->getSegmentMan()->completeSegment(cuid, nextSegment);
 	  _requestGroup->getSegmentMan()->completeSegment(cuid, nextSegment);
 	  tempSegment = nextSegment;
 	  tempSegment = nextSegment;
@@ -165,3 +189,8 @@ bool DownloadCommand::prepareForNextSegment() {
     return prepareForRetry(0);
     return prepareForRetry(0);
   }
   }
 }
 }
+
+void DownloadCommand::setTransferDecoder(const TransferEncodingHandle& transferDecoder)
+{
+  this->transferDecoder = transferDecoder;
+}

+ 5 - 8
src/DownloadCommand.h

@@ -36,11 +36,11 @@
 #define _D_DOWNLOAD_COMMAND_H_
 #define _D_DOWNLOAD_COMMAND_H_
 
 
 #include "AbstractCommand.h"
 #include "AbstractCommand.h"
-#include "TransferEncoding.h"
-#include "TimeA2.h"
-#include "PeerStat.h"
 
 
-using namespace std;
+class TransferEncoding;
+extern typedef SharedHandle<TransferEncoding> TransferEncodingHandle;
+class PeerStat;
+extern typedef SharedHandle<PeerStat> PeerStatHandle;
 
 
 class DownloadCommand : public AbstractCommand {
 class DownloadCommand : public AbstractCommand {
 private:
 private:
@@ -62,10 +62,7 @@ public:
 		  const SocketHandle& s);
 		  const SocketHandle& s);
   virtual ~DownloadCommand();
   virtual ~DownloadCommand();
 
 
-  void setTransferDecoder(const TransferEncodingHandle& transferDecoder)
-  {
-    this->transferDecoder = transferDecoder;
-  }
+  void setTransferDecoder(const TransferEncodingHandle& transferDecoder);
 
 
   void setMaxDownloadSpeedLimit(int32_t maxDownloadSpeedLimit) {
   void setMaxDownloadSpeedLimit(int32_t maxDownloadSpeedLimit) {
     this->maxDownloadSpeedLimit = maxDownloadSpeedLimit;
     this->maxDownloadSpeedLimit = maxDownloadSpeedLimit;

+ 99 - 0
src/DownloadContext.h

@@ -0,0 +1,99 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DOWNLOAD_CONTEXT_H_
+#define _D_DOWNLOAD_CONTEXT_H_
+
+#include "common.h"
+#include "FileEntry.h"
+
+class DownloadContext
+{
+protected:
+  string _dir;
+
+public:
+  DownloadContext():_dir(".") {}
+
+  virtual ~DownloadContext() {}
+
+
+  enum FILE_MODE {
+    SINGLE,
+    MULTI
+  };
+
+  virtual string getPieceHash(int32_t index) const = 0;
+  
+  virtual const Strings& getPieceHashes() const = 0;
+
+  virtual int64_t getTotalLength() const = 0;
+
+  virtual FILE_MODE getFileMode() const = 0;
+
+  virtual FileEntries getFileEntries() const = 0;
+
+  virtual string getName() const = 0;
+  
+  virtual int32_t getPieceLength() const = 0;
+
+  virtual int32_t getNumPieces() const = 0;
+
+  virtual string getPieceHashAlgo() const = 0;
+
+  /**
+   * Returns an actual file path.
+   * If this contains a single file entry, then returns its file path,
+   * for example, "/tmp/downloads/aria2.txt"
+   * If this contains multiple file entries(i,e /tmp/downloads/aria2.txt,
+   * /tmp/downloads/aria2.bin), then returns its base dir path,
+   * for example, "/tmp/downloads"
+   */
+  virtual string getActualBasePath() const = 0;
+
+  string getDir() const
+  {
+    return _dir;
+  }
+
+  void setDir(const string& dir)
+  {
+    _dir = dir;
+  }
+
+};
+
+typedef SharedHandle<DownloadContext> DownloadContextHandle;
+
+#endif // _D_DOWNLOAD_CONTEXT_H_

+ 75 - 2
src/DownloadEngine.cc

@@ -33,6 +33,15 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "DownloadEngine.h"
 #include "DownloadEngine.h"
+#include "Socket.h"
+#include "NameResolver.h"
+#include "StatCalc.h"
+#include "RequestGroup.h"
+#include "RequestGroupMan.h"
+#include "FileAllocationMan.h"
+#ifdef ENABLE_MESSAGE_DIGEST
+#include "CheckIntegrityMan.h"
+#endif // ENABLE_MESSAGE_DIGEST
 #include "Util.h"
 #include "Util.h"
 #include "LogFactory.h"
 #include "LogFactory.h"
 #include "TimeA2.h"
 #include "TimeA2.h"
@@ -41,11 +50,38 @@
 #include <sys/stat.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <errno.h>
+#include <signal.h>
 #include <algorithm>
 #include <algorithm>
 
 
-using namespace std;
+volatile sig_atomic_t globalHaltRequested;
+
+SocketEntry::SocketEntry(const SocketHandle& socket,
+			 Command* command,
+			 TYPE type):
+  socket(socket), command(command), type(type) {}
+
+bool SocketEntry::operator==(const SocketEntry& entry)
+{
+  return socket == entry.socket &&
+    command == entry.command &&
+    type == entry.type;
+}
+
+#ifdef ENABLE_ASYNC_DNS
+NameResolverEntry::NameResolverEntry(const NameResolverHandle& nameResolver,
+					     Command* command):
+  nameResolver(nameResolver), command(command) {}
+
+bool NameResolverEntry::operator==(const NameResolverEntry& entry)
+{
+  return nameResolver == entry.nameResolver &&
+    command == entry.command;
+}
+#endif // ENABLE_ASYNC_DNS
 
 
 DownloadEngine::DownloadEngine():logger(LogFactory::getInstance()),
 DownloadEngine::DownloadEngine():logger(LogFactory::getInstance()),
+				 _statCalc(0),
+				 _haltRequested(false),
 				 noWait(false),
 				 noWait(false),
 				 _requestGroupMan(0),
 				 _requestGroupMan(0),
 				 _fileAllocationMan(0)
 				 _fileAllocationMan(0)
@@ -83,7 +119,6 @@ void DownloadEngine::executeCommand(Command::STATUS statusFilter)
 }
 }
 
 
 void DownloadEngine::run() {
 void DownloadEngine::run() {
-  initStatistics();
   Time cp;
   Time cp;
   cp.setTimeInSec(0);
   cp.setTimeInSec(0);
   Commands activeCommands;
   Commands activeCommands;
@@ -232,6 +267,38 @@ bool DownloadEngine::deleteSocketForWriteCheck(const SocketHandle& socket,
   return deleteSocket(entry);
   return deleteSocket(entry);
 }
 }
 
 
+void DownloadEngine::calculateStatistics()
+{
+  if(!_statCalc.isNull()) {
+    _statCalc->calculateStat(_requestGroupMan, _fileAllocationMan, _checkIntegrityMan);
+  }
+}
+
+void DownloadEngine::onEndOfRun()
+{
+  _requestGroupMan->closeFile();
+  _requestGroupMan->save();
+}
+
+void DownloadEngine::afterEachIteration()
+{
+  if(globalHaltRequested) {
+    globalHaltRequested = false;
+    _haltRequested = true;
+    _requestGroupMan->halt();
+  }
+}
+
+void DownloadEngine::fillCommand()
+{
+  addCommand(_requestGroupMan->getInitialCommands(this));
+}
+
+void DownloadEngine::setStatCalc(const StatCalcHandle& statCalc)
+{
+  _statCalc = statCalc;
+}
+
 #ifdef ENABLE_ASYNC_DNS
 #ifdef ENABLE_ASYNC_DNS
 bool DownloadEngine::addNameResolverCheck(const NameResolverHandle& resolver,
 bool DownloadEngine::addNameResolverCheck(const NameResolverHandle& resolver,
 					  Command* command) {
 					  Command* command) {
@@ -262,4 +329,10 @@ bool DownloadEngine::deleteNameResolverCheck(const NameResolverHandle& resolver,
     return true;
     return true;
   }
   }
 }
 }
+
+void DownloadEngine::addCommand(const Commands& commands)
+{
+  this->commands.insert(this->commands.end(), commands.begin(), commands.end());
+}
+
 #endif // ENABLE_ASYNC_DNS
 #endif // ENABLE_ASYNC_DNS

+ 48 - 35
src/DownloadEngine.h

@@ -35,21 +35,27 @@
 #ifndef _D_DOWNLOAD_ENGINE_H_
 #ifndef _D_DOWNLOAD_ENGINE_H_
 #define _D_DOWNLOAD_ENGINE_H_
 #define _D_DOWNLOAD_ENGINE_H_
 
 
-#include "Command.h"
-#include "Socket.h"
-#include "SegmentMan.h"
 #include "common.h"
 #include "common.h"
-#include "Logger.h"
-#include "Option.h"
-#include "NameResolver.h"
-#include "RequestGroupMan.h"
-#include "FileAllocationMan.h"
+#include "Command.h"
+
+class SocketCore;
+extern typedef SharedHandle<SocketCore> SocketHandle;
+extern typedef deque<SocketHandle> Sockets;
+class Logger;
+class Option;
+class NameResolver;
+extern typedef SharedHandle<NameResolver> NameResolverHandle;
+class RequestGroupMan;
+extern typedef SharedHandle<RequestGroupMan> RequestGroupManHandle;
+class FileAllocationMan;
+extern typedef SharedHandle<FileAllocationMan> FileAllocationManHandle;
+class StatCalc;
+extern typedef SharedHandle<StatCalc> StatCalcHandle;
 #ifdef ENABLE_MESSAGE_DIGEST
 #ifdef ENABLE_MESSAGE_DIGEST
-# include "CheckIntegrityMan.h"
+class CheckIntegrityMan;
+extern typedef SharedHandle<CheckIntegrityMan> CheckIntegrityManHandle;
 #endif // ENABLE_MESSAGE_DIGEST
 #endif // ENABLE_MESSAGE_DIGEST
 
 
-typedef deque<SocketHandle> Sockets;
-
 class SocketEntry {
 class SocketEntry {
 public:
 public:
   enum TYPE {
   enum TYPE {
@@ -63,15 +69,9 @@ public:
 public:
 public:
   SocketEntry(const SocketHandle& socket,
   SocketEntry(const SocketHandle& socket,
 	      Command* command,
 	      Command* command,
-	      TYPE type):
-    socket(socket), command(command), type(type) {}
-  ~SocketEntry() {}
-
-  bool operator==(const SocketEntry& entry) {
-    return socket == entry.socket &&
-      command == entry.command &&
-      type == entry.type;
-  }
+	      TYPE type);
+
+  bool operator==(const SocketEntry& entry);
 };
 };
 
 
 typedef deque<SocketEntry> SocketEntries;
 typedef deque<SocketEntry> SocketEntries;
@@ -83,14 +83,9 @@ public:
   Command* command;
   Command* command;
 public:
 public:
   NameResolverEntry(const NameResolverHandle& nameResolver,
   NameResolverEntry(const NameResolverHandle& nameResolver,
-		    Command* command):
-    nameResolver(nameResolver), command(command) {}
-  ~NameResolverEntry() {}
+		    Command* command);
 
 
-  bool operator==(const NameResolverEntry& entry) {
-    return nameResolver == entry.nameResolver &&
-      command == entry.command;
-  }
+  bool operator==(const NameResolverEntry& entry);
 };
 };
 
 
 typedef deque<NameResolverEntry> NameResolverEntries;
 typedef deque<NameResolverEntry> NameResolverEntries;
@@ -108,16 +103,26 @@ private:
   fd_set wfdset;
   fd_set wfdset;
   int32_t fdmax;
   int32_t fdmax;
 
 
+  const Logger* logger;
+  
+  StatCalcHandle _statCalc;
+
+  bool _haltRequested;
+
   void shortSleep() const;
   void shortSleep() const;
   bool addSocket(const SocketEntry& socketEntry);
   bool addSocket(const SocketEntry& socketEntry);
   bool deleteSocket(const SocketEntry& socketEntry);
   bool deleteSocket(const SocketEntry& socketEntry);
   void executeCommand(Command::STATUS statusFilter);
   void executeCommand(Command::STATUS statusFilter);
-protected:
-  const Logger* logger;
-  virtual void initStatistics() = 0;
-  virtual void calculateStatistics() = 0;
-  virtual void onEndOfRun() = 0;
-  virtual void afterEachIteration() {}
+
+  /**
+   * Delegates to StatCalc
+   */
+  void calculateStatistics();
+
+  void onEndOfRun();
+
+  void afterEachIteration();
+
 public:
 public:
   bool noWait;
   bool noWait;
   Commands commands;
   Commands commands;
@@ -152,11 +157,19 @@ public:
 			       Command* command);
 			       Command* command);
 #endif // ENABLE_ASYNC_DNS
 #endif // ENABLE_ASYNC_DNS
 
 
-  void addCommand(const Commands& commands)
+  void addCommand(const Commands& commands);
+
+  void fillCommand();
+
+  void setStatCalc(const StatCalcHandle& statCalc);
+
+  bool isHaltRequested() const
   {
   {
-    this->commands.insert(this->commands.end(), commands.begin(), commands.end());
+    return _haltRequested;
   }
   }
 };
 };
 
 
+typedef SharedHandle<DownloadEngine> DownloadEngineHandle;
+
 #endif // _D_DOWNLOAD_ENGINE_H_
 #endif // _D_DOWNLOAD_ENGINE_H_
 
 

+ 34 - 169
src/DownloadEngineFactory.cc

@@ -33,46 +33,31 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "DownloadEngineFactory.h"
 #include "DownloadEngineFactory.h"
+#include "LogFactory.h"
+#include "Option.h"
+#include "RequestGroup.h"
+#include "DownloadEngine.h"
+#include "RequestGroupMan.h"
+#include "FileAllocationMan.h"
+#ifdef ENABLE_MESSAGE_DIGEST
+# include "CheckIntegrityMan.h"
+#endif // ENABLE_MESSAGE_DIGEST
 #include "prefs.h"
 #include "prefs.h"
-#include "DefaultDiskWriter.h"
-#include "InitiateConnectionCommandFactory.h"
 #include "Util.h"
 #include "Util.h"
-#include "FileAllocator.h"
-#include "FileAllocationMonitor.h"
-#include "FillRequestGroupCommand.h"
 #include "CUIDCounter.h"
 #include "CUIDCounter.h"
+#include "FillRequestGroupCommand.h"
 #include "FileAllocationDispatcherCommand.h"
 #include "FileAllocationDispatcherCommand.h"
-#include "FileAllocationMan.h"
 #include "AutoSaveCommand.h"
 #include "AutoSaveCommand.h"
-#ifdef ENABLE_MESSAGE_DIGEST
-# include "CheckIntegrityMan.h"
-#endif // ENABLE_MESSAGE_DIGEST
-#ifdef ENABLE_BITTORRENT
-# include "PeerListenCommand.h"
-# include "TrackerWatcherCommand.h"
-# include "TrackerUpdateCommand.h"
-# include "TorrentAutoSaveCommand.h"
-# include "SeedCheckCommand.h"
-# include "PeerChokeCommand.h"
-# include "HaveEraseCommand.h"
-# include "ActivePeerConnectionCommand.h"
-# include "UnionSeedCriteria.h"
-# include "TimeSeedCriteria.h"
-# include "ShareRatioSeedCriteria.h"
-# include "DefaultPieceStorage.h"
-# include "DefaultPeerStorage.h"
-# include "DefaultBtAnnounce.h"
-# include "DefaultBtProgressInfoFile.h"
-#endif // ENABLE_BITTORRENT
+#include "HaveEraseCommand.h"
+#include "PeerListenCommand.h"
 
 
-ConsoleDownloadEngine*
-DownloadEngineFactory::newConsoleEngine(const Option* op,
-					const RequestGroups& requestGroups)
+DownloadEngineFactory::DownloadEngineFactory():
+  _logger(LogFactory::getInstance()) {}
+
+DownloadEngineHandle
+DownloadEngineFactory::newDownloadEngine(Option* op,
+					 const RequestGroups& requestGroups)
 {
 {
-  // set PREF_OUT parameter to requestGroup in non-multi download mode.
-  if(requestGroups.size() == 1) {
-    requestGroups.front()->setUserDefinedFilename(op->get(PREF_OUT));
-  }
   RequestGroups workingSet;
   RequestGroups workingSet;
   RequestGroups reservedSet;
   RequestGroups reservedSet;
   if(op->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS) < (int32_t)requestGroups.size()) {
   if(op->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS) < (int32_t)requestGroups.size()) {
@@ -83,109 +68,24 @@ DownloadEngineFactory::newConsoleEngine(const Option* op,
     workingSet = requestGroups;
     workingSet = requestGroups;
   }
   }
 
 
-  ConsoleDownloadEngine* e = new ConsoleDownloadEngine();
+  DownloadEngineHandle e = new DownloadEngine();
   e->option = op;
   e->option = op;
-  RequestGroupManHandle requestGroupMan = new RequestGroupMan(workingSet,
-							      op->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS));
+  RequestGroupManHandle requestGroupMan =
+    new RequestGroupMan(workingSet,
+			op->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS));
   requestGroupMan->addReservedGroup(reservedSet);
   requestGroupMan->addReservedGroup(reservedSet);
   e->_requestGroupMan = requestGroupMan;
   e->_requestGroupMan = requestGroupMan;
   e->_fileAllocationMan = new FileAllocationMan();
   e->_fileAllocationMan = new FileAllocationMan();
 #ifdef ENABLE_MESSAGE_DIGEST
 #ifdef ENABLE_MESSAGE_DIGEST
   e->_checkIntegrityMan = new CheckIntegrityMan();
   e->_checkIntegrityMan = new CheckIntegrityMan();
 #endif // ENABLE_MESSAGE_DIGEST
 #endif // ENABLE_MESSAGE_DIGEST
-  e->commands.push_back(new FillRequestGroupCommand(CUIDCounterSingletonHolder::instance()->newID(), e, 1));
-  e->commands.push_back(new FileAllocationDispatcherCommand(CUIDCounterSingletonHolder::instance()->newID(), e));
-  e->commands.push_back(new AutoSaveCommand(CUIDCounterSingletonHolder::instance()->newID(), e, op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
-  return e;
-}
-
-ConsoleDownloadEngine*
-DownloadEngineFactory::newConsoleEngine(const Option* op,
-					const Requests& requests,
-					const Requests& reserved)
-{
-  ConsoleDownloadEngine* e = new ConsoleDownloadEngine();
-  e->option = op;
-//   e->segmentMan = new SegmentMan();
-//   e->segmentMan->diskWriter = DefaultDiskWriter::createNewDiskWriter(op);
-//   e->segmentMan->dir = op->get(PREF_DIR);
-//   e->segmentMan->ufilename = op->get(PREF_OUT);
-//   e->segmentMan->option = op;
-//   e->segmentMan->reserved = reserved;
-  
-//   int cuidCounter = 1;
-//   for(Requests::const_iterator itr = requests.begin();
-//       itr != requests.end();
-//       itr++, cuidCounter++) {
-//     e->commands.push_back(InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuidCounter, *itr, e));
-//   }
-  return e;
-}
-
-#ifdef ENABLE_BITTORRENT
-TorrentConsoleDownloadEngine*
-DownloadEngineFactory::newTorrentConsoleEngine(const BtContextHandle& btContext,
-					       const Option* op,
-					       const Strings& targetFiles)
-{
-  TorrentConsoleDownloadEngine* te = new TorrentConsoleDownloadEngine();
-  te->option = op;
-  RequestGroupManHandle requestGroupMan = new RequestGroupMan();
-  te->_requestGroupMan = requestGroupMan;
-  //  ByteArrayDiskWriter* byteArrayDiskWriter = new ByteArrayDiskWriter();
-//   te->segmentMan = new SegmentMan();
-//   te->segmentMan->diskWriter = byteArrayDiskWriter;
-//   te->segmentMan->option = op;
-  BtRuntimeHandle btRuntime(new BtRuntime());
-  BtRegistry::registerBtRuntime(btContext->getInfoHashAsString(), btRuntime);
-
-  PieceStorageHandle pieceStorage(new DefaultPieceStorage(btContext, op));
-  BtRegistry::registerPieceStorage(btContext->getInfoHashAsString(), pieceStorage);
-
-  PeerStorageHandle peerStorage(new DefaultPeerStorage(btContext, op));
-  BtRegistry::registerPeerStorage(btContext->getInfoHashAsString(), peerStorage);
-
-  BtAnnounceHandle btAnnounce(new DefaultBtAnnounce(btContext, op));
-  BtRegistry::registerBtAnnounce(btContext->getInfoHashAsString(), btAnnounce);
-  btAnnounce->shuffleAnnounce();
-
-  BtProgressInfoFileHandle btProgressInfoFile(new DefaultBtProgressInfoFile(btContext, op));
-  BtRegistry::registerBtProgressInfoFile(btContext->getInfoHashAsString(),
-					 btProgressInfoFile);
-
-  BtRegistry::registerPeerObjectCluster(btContext->getInfoHashAsString(),
-					new PeerObjectCluster());
-
-  /*
-  DefaultBtMessageFactoryAdaptorHandle factoryAdaptor =
-    new DefaultBtMessageFactoryAdaptor();
-  BtRegistry::registerBtMessageFactoryAdaptor(btContext->getInfoHashAsString(),
-					      factoryAdaptor);
-
-  BtMessageFactoryClusterHandle factoryCluster = new BtMessageFactoryCluster();
-  BtRegistry::registerBtMessageFactoryCluster(btContext->getInfoHashAsString(),
-					      factoryCluster);
-
-  BtMessageDispatcherClusterHandle dispatcherCluster =
-    new BtMessageDispatcherCluster();
-  BtRegistry::registerBtMessageDispatcherCluster(btContext->getInfoHashAsString(),
-						 dispatcherCluster);
-  */
-  te->setBtContext(btContext);
-  // initialize file storage
-  pieceStorage->initStorage();
-
-  Integers selectIndexes;
-  Util::unfoldRange(op->get(PREF_SELECT_FILE), selectIndexes);
-  if(selectIndexes.size()) {
-    pieceStorage->setFileFilter(selectIndexes);
-  } else {
-    pieceStorage->setFileFilter(targetFiles);
-  }
+  e->commands.push_back(new FillRequestGroupCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get(), 1));
+  e->commands.push_back(new FileAllocationDispatcherCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get()));
+  e->commands.push_back(new AutoSaveCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get(), op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
+  e->commands.push_back(new HaveEraseCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get(), 10));
 
 
   PeerListenCommand* listenCommand =
   PeerListenCommand* listenCommand =
-    new PeerListenCommand(CUIDCounterSingletonHolder::instance()->newID(),
-			  te, btContext);
+    new PeerListenCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get());
   int32_t port;
   int32_t port;
   int32_t listenPort = op->getAsInt(PREF_LISTEN_PORT);
   int32_t listenPort = op->getAsInt(PREF_LISTEN_PORT);
   if(listenPort == -1) {
   if(listenPort == -1) {
@@ -194,48 +94,13 @@ DownloadEngineFactory::newTorrentConsoleEngine(const BtContextHandle& btContext,
     port = listenCommand->bindPort(listenPort, listenPort);
     port = listenCommand->bindPort(listenPort, listenPort);
   }
   }
   if(port == -1) {
   if(port == -1) {
-    printf(_("Errors occurred while binding port.\n"));
-    exit(EXIT_FAILURE);
+    _logger->error(_("Errors occurred while binding port.\n"));
+    delete listenCommand;
+  } else {
+    op->put(PREF_LISTEN_PORT, Util::itos(port).c_str());
+    e->commands.push_back(listenCommand);
   }
   }
-  btRuntime->setListenPort(port);
-  te->commands.push_back(listenCommand);
-  
-  te->commands.push_back(new TrackerWatcherCommand(CUIDCounterSingletonHolder::instance()->newID(),
-						   te,
-						   btContext));
-  te->commands.push_back(new TrackerUpdateCommand(CUIDCounterSingletonHolder::instance()->newID(),
-						  te,
-						  btContext));
-  te->commands.push_back(new TorrentAutoSaveCommand(CUIDCounterSingletonHolder::instance()->newID(),
-						    te,
-						    btContext,
-						    op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
-  te->commands.push_back(new PeerChokeCommand(CUIDCounterSingletonHolder::instance()->newID(),
-					      te,
-					      btContext,
-					      10));
-  te->commands.push_back(new HaveEraseCommand(CUIDCounterSingletonHolder::instance()->newID(),
-					      te,
-					      btContext,
-					      10));
-  te->commands.push_back(new ActivePeerConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(),
-							 te,
-							 btContext,
-							 30));
+  //btRuntime->setListenPort(port);
 
 
-  SharedHandle<UnionSeedCriteria> unionCri = new UnionSeedCriteria();
-  if(op->defined(PREF_SEED_TIME)) {
-    unionCri->addSeedCriteria(new TimeSeedCriteria(op->getAsInt(PREF_SEED_TIME)*60));
-  }
-  if(op->defined(PREF_SEED_RATIO)) {
-    unionCri->addSeedCriteria(new ShareRatioSeedCriteria(op->getAsDouble(PREF_SEED_RATIO), btContext));
-  }
-  if(unionCri->getSeedCriterion().size() > 0) {
-    te->commands.push_back(new SeedCheckCommand(CUIDCounterSingletonHolder::instance()->newID(),
-						te,
-						btContext,
-						unionCri));
-  }
-  return te;
+  return e;
 }
 }
-#endif // ENABLE_BITTORRENT

+ 13 - 18
src/DownloadEngineFactory.h

@@ -36,28 +36,23 @@
 #define _D_DOWNLOAD_ENGINE_FACTORY_H_
 #define _D_DOWNLOAD_ENGINE_FACTORY_H_
 
 
 #include "common.h"
 #include "common.h"
-#include "ConsoleDownloadEngine.h"
-#ifdef ENABLE_BITTORRENT
-# include "TorrentConsoleDownloadEngine.h"
-#endif // ENABLE_BITTORRENT
+
+class Logger;
+class Option;
+class RequestGroup;
+extern typedef SharedHandle<RequestGroup> RequestGroupHandle;
+extern typedef deque<RequestGroupHandle> RequestGroups;
+class DownloadEngine;
+extern typedef SharedHandle<DownloadEngine> DownloadEngineHandle;
 
 
 class DownloadEngineFactory {
 class DownloadEngineFactory {
+private:
+  const Logger* _logger;
 public:
 public:
-  static ConsoleDownloadEngine*
-  newConsoleEngine(const Option* op,
-		   const RequestGroups& requestGroups);
-
-  static ConsoleDownloadEngine*
-  newConsoleEngine(const Option* option,
-		   const Requests& requests,
-		   const Requests& reserved);
+  DownloadEngineFactory();
 
 
-#ifdef ENABLE_BITTORRENT
-  static TorrentConsoleDownloadEngine*
-  newTorrentConsoleEngine(const BtContextHandle& btContext,
-			  const Option* option, 
-			  const Strings& targetFiles);
-#endif // ENABLE_BITTORRENT
+  DownloadEngineHandle
+  newDownloadEngine(Option* op, const RequestGroups& requestGroups);
 };
 };
 
 
 #endif // _D_DOWNLOAD_ENGINE_FACTORY_H_
 #endif // _D_DOWNLOAD_ENGINE_FACTORY_H_

+ 23 - 0
src/File.cc

@@ -37,6 +37,11 @@
 #include "a2io.h"
 #include "a2io.h"
 #include <libgen.h>
 #include <libgen.h>
 
 
+#ifdef __MINGW32__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif // __MINGW32__
+
 File::File(const string& name):name(name) {}
 File::File(const string& name):name(name) {}
 
 
 File::~File() {}
 File::~File() {}
@@ -140,3 +145,21 @@ bool File::isDir(const string& filename)
 {
 {
   return File(filename).isDir();
   return File(filename).isDir();
 }
 }
+
+bool File::renameTo(const string& dest)
+{
+#ifdef __MINGW32__
+  /* MinGW's rename() doesn't delete an existing destination */
+  if (_access(dest.c_str(), 0) == 0) {
+    if (_unlink(dest.c_str()) != 0) {
+      return false;
+    }
+  }
+#endif // __MINGW32__
+  if(rename(name.c_str(), dest.c_str()) == 0) {
+    name = dest;
+    return true;
+  } else {
+    return false;
+  }
+}

+ 2 - 0
src/File.h

@@ -96,6 +96,8 @@ public:
   string getDirname() const;
   string getDirname() const;
 
 
   static bool isDir(const string& filename);
   static bool isDir(const string& filename);
+
+  bool renameTo(const string& dest);
 };
 };
 
 
 #endif // _D_FILE_H_
 #endif // _D_FILE_H_

+ 27 - 24
src/FileAllocationCommand.cc

@@ -33,45 +33,48 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "FileAllocationCommand.h"
 #include "FileAllocationCommand.h"
-#include "InitiateConnectionCommandFactory.h"
+#include "FileAllocationMan.h"
+#include "FileAllocationEntry.h"
 #include "message.h"
 #include "message.h"
 #include "DownloadCommand.h"
 #include "DownloadCommand.h"
 #include "prefs.h"
 #include "prefs.h"
 #include "Util.h"
 #include "Util.h"
 
 
+FileAllocationCommand::FileAllocationCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const FileAllocationEntryHandle& fileAllocationEntry):
+  RealtimeCommand(cuid, requestGroup, e),
+  _fileAllocationEntry(fileAllocationEntry) {}
+
+FileAllocationCommand::~FileAllocationCommand() {}
+
 bool FileAllocationCommand::executeInternal()
 bool FileAllocationCommand::executeInternal()
 {
 {
-  _fileAllocationEntry->allocateChunk();
-  
-  if(_fileAllocationEntry->finished()) {
-    logger->debug(MSG_ALLOCATION_COMPLETED,
-		  _timer.difference(),
-		  Util::llitos(_requestGroup->getTotalLength(), true).c_str());
-    
-    _e->_fileAllocationMan->markCurrentFileAllocationEntryDone();
-    
-    if(_timer.difference() <= _e->option->getAsInt(PREF_DIRECT_DOWNLOAD_TIMEOUT) &&
-       _fileAllocationEntry->getNextDownloadCommand()) {
-      _e->commands.push_back(_fileAllocationEntry->popNextDownloadCommand());
-    } else {
-      Commands commands = _requestGroup->createNextCommandWithAdj(_e, -1);
-      Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, _fileAllocationEntry->getCurrentRequest(), _requestGroup, _e);
+  if(_e->isHaltRequested()) {
+    return true;
+  }
+  try {
+    _fileAllocationEntry->allocateChunk();
+    if(_fileAllocationEntry->finished()) {
+      logger->debug(MSG_ALLOCATION_COMPLETED,
+		    _timer.difference(),
+		    Util::llitos(_requestGroup->getTotalLength(), true).c_str());
+      _e->_fileAllocationMan->markCurrentFileAllocationEntryDone();
+      
+      _e->addCommand(_fileAllocationEntry->prepareForNextAction(_e));
       
       
-      commands.push_front(command);
-    
-      _e->addCommand(commands);
+      return true;
+    } else {
+      _e->commands.push_back(this);
+      return false;
     }
     }
-    return true;
-  } else {
-    _e->commands.push_back(this);
-    return false;
+  } catch(Exception* e) {
+    _e->_fileAllocationMan->markCurrentFileAllocationEntryDone();
+    throw;
   }
   }
 }
 }
 
 
 bool FileAllocationCommand::handleException(Exception* e)
 bool FileAllocationCommand::handleException(Exception* e)
 {
 {
   logger->error(MSG_FILE_ALLOCATION_FAILURE, e, cuid);
   logger->error(MSG_FILE_ALLOCATION_FAILURE, e, cuid);
-  delete e;
   logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str());
   logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str());
   return true;
   return true;
 }
 }

+ 7 - 4
src/FileAllocationCommand.h

@@ -37,16 +37,19 @@
 
 
 #include "RealtimeCommand.h"
 #include "RealtimeCommand.h"
 #include "TimeA2.h"
 #include "TimeA2.h"
-#include "FileAllocationEntry.h"
+
+class FileAllocationEntry;
+extern typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;
+class Exception;
 
 
 class FileAllocationCommand : public RealtimeCommand {
 class FileAllocationCommand : public RealtimeCommand {
 private:
 private:
   FileAllocationEntryHandle _fileAllocationEntry;
   FileAllocationEntryHandle _fileAllocationEntry;
   Time _timer;
   Time _timer;
 public:
 public:
-  FileAllocationCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const FileAllocationEntryHandle& fileAllocationEntry):
-    RealtimeCommand(cuid, requestGroup, e),
-    _fileAllocationEntry(fileAllocationEntry) {}
+  FileAllocationCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const FileAllocationEntryHandle& fileAllocationEntry);
+
+  virtual ~FileAllocationCommand();
 
 
   virtual bool executeInternal();
   virtual bool executeInternal();
 
 

+ 18 - 5
src/FileAllocationDispatcherCommand.cc

@@ -33,22 +33,35 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "FileAllocationDispatcherCommand.h"
 #include "FileAllocationDispatcherCommand.h"
+#include "DownloadEngine.h"
+#include "RequestGroupMan.h"
+#include "FileAllocationMan.h"
+#include "FileAllocationEntry.h"
 #include "FileAllocationCommand.h"
 #include "FileAllocationCommand.h"
 #include "message.h"
 #include "message.h"
+#include "CUIDCounter.h"
+
+FileAllocationDispatcherCommand::FileAllocationDispatcherCommand(int32_t cuid, DownloadEngine* e):
+  Command(cuid), _e(e)
+{
+  setStatusRealtime();
+}
+
+FileAllocationDispatcherCommand::~FileAllocationDispatcherCommand() {}
 
 
 bool FileAllocationDispatcherCommand::execute()
 bool FileAllocationDispatcherCommand::execute()
 {
 {
-  if(_e->_requestGroupMan->downloadFinished()) {
+  if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
     return true;
     return true;
   }
   }
-  
   if(!_e->_fileAllocationMan->isFileAllocationBeingExecuted() &&
   if(!_e->_fileAllocationMan->isFileAllocationBeingExecuted() &&
      _e->_fileAllocationMan->nextFileAllocationEntryExists()) {
      _e->_fileAllocationMan->nextFileAllocationEntryExists()) {
     FileAllocationEntryHandle entry = _e->_fileAllocationMan->popNextFileAllocationEntry();
     FileAllocationEntryHandle entry = _e->_fileAllocationMan->popNextFileAllocationEntry();
-    logger->info(MSG_FILE_ALLOCATION_DISPATCH,
-		 entry->getCUID());
+    // TODO we have to change message
+    int32_t newCUID = CUIDCounterSingletonHolder::instance()->newID();
+    logger->info(MSG_FILE_ALLOCATION_DISPATCH, newCUID);
     FileAllocationCommand* command =
     FileAllocationCommand* command =
-      new FileAllocationCommand(entry->getCUID(),
+      new FileAllocationCommand(newCUID,
 				entry->getRequestGroup(),
 				entry->getRequestGroup(),
 				_e,
 				_e,
 				entry);
 				entry);

+ 5 - 6
src/FileAllocationDispatcherCommand.h

@@ -36,17 +36,16 @@
 #define _D_FILE_ALLOCATION_DISPATCHER_COMMAND_H_
 #define _D_FILE_ALLOCATION_DISPATCHER_COMMAND_H_
 
 
 #include "Command.h"
 #include "Command.h"
-#include "DownloadEngine.h"
+
+class DownloadEngine;
 
 
 class FileAllocationDispatcherCommand : public Command {
 class FileAllocationDispatcherCommand : public Command {
 private:
 private:
   DownloadEngine* _e;
   DownloadEngine* _e;
 public:
 public:
-  FileAllocationDispatcherCommand(int cuid, DownloadEngine* e):
-    Command(cuid), _e(e)
-  {
-    setStatusRealtime();
-  }
+  FileAllocationDispatcherCommand(int32_t cuid, DownloadEngine* e);
+  
+  virtual ~FileAllocationDispatcherCommand();
 
 
   virtual bool execute();
   virtual bool execute();
 };
 };

+ 26 - 13
src/FileAllocationEntry.cc

@@ -33,22 +33,35 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "FileAllocationEntry.h"
 #include "FileAllocationEntry.h"
+#include "FileAllocationIterator.h"
+#include "DownloadEngine.h"
+#include "RequestGroup.h"
+#include "PieceStorage.h"
+#include "DiskAdaptor.h"
 
 
-#define BUFSIZE 16*1024
+FileAllocationEntry::FileAllocationEntry(RequestGroup* requestGroup, Command* nextCommand):
+  RequestGroupEntry(requestGroup, nextCommand),
+  _fileAllocationIterator(requestGroup->getPieceStorage()->getDiskAdaptor()->fileAllocationIterator())
+{}
 
 
-void FileAllocationEntry::allocateChunk()
+FileAllocationEntry:: ~FileAllocationEntry() {}
+
+int64_t FileAllocationEntry::getCurrentLength()
+{
+  return _fileAllocationIterator->getCurrentLength();
+}
+
+int64_t FileAllocationEntry::getTotalLength()
 {
 {
-  int32_t bufSize = BUFSIZE;
-  char buf[BUFSIZE];
-  memset(buf, 0, bufSize);
-  
-  _requestGroup->getSegmentMan()->diskWriter->writeData(buf, bufSize, _offset);
-  _offset += bufSize;
+  return _fileAllocationIterator->getTotalLength();
+}
 
 
-  int64_t totalLength = _requestGroup->getSegmentMan()->totalSize;
-  if(totalLength < _offset) {
-    _requestGroup->getSegmentMan()->diskWriter->truncate(totalLength);
-    _offset = totalLength;
-  }
+bool FileAllocationEntry::finished()
+{
+  return _fileAllocationIterator->finished();
 }
 }
 
 
+void FileAllocationEntry::allocateChunk()
+{
+  _fileAllocationIterator->allocateChunk();
+}

+ 16 - 19
src/FileAllocationEntry.h

@@ -37,32 +37,29 @@
 
 
 #include "RequestGroupEntry.h"
 #include "RequestGroupEntry.h"
 
 
-class FileAllocationEntry : public RequestGroupEntry {
+class FileAllocationIterator;
+extern typedef SharedHandle<FileAllocationIterator> FileAllocationIteratorHandle;
+class Command;
+extern typedef deque<Command*> Commands;
+class DownloadEngine;
+
+class FileAllocationEntry : public RequestGroupEntry, public ProgressAwareEntry {
 private:
 private:
-  int64_t _offset;
+  FileAllocationIteratorHandle _fileAllocationIterator;
 public:
 public:
-  FileAllocationEntry(int cuid,
-		      const RequestHandle& currentRequest,
-		      RequestGroup* requestGroup,
-		      DownloadCommand* nextDownloadCommand = 0,
-		      int64_t offset = 0):
-    RequestGroupEntry(cuid, currentRequest, requestGroup, nextDownloadCommand),
-    _offset(offset)
-  {}
+  FileAllocationEntry(RequestGroup* requestGroup, Command* nextCommand = 0);
+
+  ~FileAllocationEntry();
 
 
-  virtual ~FileAllocationEntry() {}
+  virtual int64_t getCurrentLength();
 
 
-  virtual int64_t getCurrentLength() const
-  {
-    return _offset;
-  }
+  virtual int64_t getTotalLength();
 
 
-  virtual bool finished() const
-  {
-    return _requestGroup->getTotalLength() <= _offset;
-  }
+  virtual bool finished();
 
 
   void allocateChunk();
   void allocateChunk();
+
+  virtual Commands prepareForNextAction(DownloadEngine* e) = 0;
 };
 };
 
 
 typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;
 typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;

+ 56 - 0
src/FileAllocationIterator.h

@@ -0,0 +1,56 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_FILE_ALLOCATION_ITERATOR_H_
+#define _D_FILE_ALLOCATION_ITERATOR_H_
+
+#include "common.h"
+
+class FileAllocationIterator
+{
+public:
+  virtual ~FileAllocationIterator() {}
+
+  virtual void allocateChunk() = 0;
+
+  virtual bool finished() = 0;
+
+  virtual int64_t getCurrentLength() = 0;
+
+  virtual int64_t getTotalLength() = 0;
+};
+
+typedef SharedHandle<FileAllocationIterator> FileAllocationIteratorHandle;
+
+#endif // _D_FILE_ALLOCATION_ITERATOR_H_

+ 39 - 29
src/TorrentConsoleDownloadEngine.cc → src/FileAllocationMan.cc

@@ -32,40 +32,50 @@
  * files in the program, then also delete it here.
  * files in the program, then also delete it here.
  */
  */
 /* copyright --> */
 /* copyright --> */
-#include "TorrentConsoleDownloadEngine.h"
-#include "Util.h"
-#include <signal.h>
+#include "FileAllocationMan.h"
+#include "FileAllocationEntry.h"
 
 
-volatile sig_atomic_t btHaltRequested = 0;
+FileAllocationMan::FileAllocationMan():_currentFileAllocationEntry(0) {}
 
 
-TorrentConsoleDownloadEngine::TorrentConsoleDownloadEngine() {}
+FileAllocationMan::~FileAllocationMan() {}
 
 
-TorrentConsoleDownloadEngine::~TorrentConsoleDownloadEngine() {}
+bool FileAllocationMan::isFileAllocationBeingExecuted() const
+{
+  return _currentFileAllocationEntry.get() != 0;
+}
 
 
-void TorrentConsoleDownloadEngine::sendStatistics() {
-  printf("\r                                                                             ");
-  printf("\r");
-  if(pieceStorage->downloadFinished()) {
-    printf("Download Completed.");
-  } else {
-    printf("%sB/%sB %d%% %s D:%.2f",
-	   Util::abbrevSize(downloadLength).c_str(),
-	   Util::abbrevSize(totalLength).c_str(),
-	   (totalLength == 0 ?
-	    0 : (int)((downloadLength*100)/totalLength)),
-	   avgSpeed == 0 ? "-" : Util::secfmt(eta).c_str(),
-	   downloadSpeed/1024.0);
-  }
-  printf(" U:%.2f(%sB) %d peers",
-	 uploadSpeed/1024.0,
-	 Util::abbrevSize(uploadLength).c_str(),
-	 btRuntime->getConnections());
-  fflush(stdout);	 
+FileAllocationEntryHandle FileAllocationMan::getCurrentFileAllocationEntry()
+{
+  return _currentFileAllocationEntry;
+}
+
+void FileAllocationMan::markCurrentFileAllocationEntryDone()
+{
+  _currentFileAllocationEntry = 0;
+}
+
+bool FileAllocationMan::nextFileAllocationEntryExists() const
+{
+  return !_fileAllocationEntries.empty();
 }
 }
 
 
-void TorrentConsoleDownloadEngine::afterEachIteration() {
-  if(btHaltRequested) {
-    btRuntime->setHalt(true);
+FileAllocationEntryHandle FileAllocationMan::popNextFileAllocationEntry()
+{
+  if(!nextFileAllocationEntryExists()) {
+    return 0;
   }
   }
-  TorrentDownloadEngine::afterEachIteration();
+  FileAllocationEntryHandle entry = _fileAllocationEntries.front();
+  _fileAllocationEntries.pop_front();
+  _currentFileAllocationEntry = entry;
+  return entry;
+}
+
+void FileAllocationMan::pushFileAllocationEntry(const FileAllocationEntryHandle& entry)
+{
+  _fileAllocationEntries.push_back(entry);
+}
+
+int32_t FileAllocationMan::countFileAllocationEntryInQueue() const
+{
+  return _fileAllocationEntries.size();
 }
 }

+ 14 - 38
src/FileAllocationMan.h

@@ -36,57 +36,33 @@
 #define _D_FILE_ALLOCATION_MAN_H_
 #define _D_FILE_ALLOCATION_MAN_H_
 
 
 #include "common.h"
 #include "common.h"
-#include "Request.h"
-#include "RequestGroup.h"
-#include "FileAllocationEntry.h"
+
+class FileAllocationEntry;
+extern typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;
+extern typedef deque<FileAllocationEntryHandle> FileAllocationEntries;
 
 
 class FileAllocationMan {
 class FileAllocationMan {
 private:
 private:
   FileAllocationEntries _fileAllocationEntries;
   FileAllocationEntries _fileAllocationEntries;
   FileAllocationEntryHandle _currentFileAllocationEntry;
   FileAllocationEntryHandle _currentFileAllocationEntry;
 public:
 public:
-  FileAllocationMan():_currentFileAllocationEntry(0) {}
+  FileAllocationMan();
+
+  ~FileAllocationMan();
 
 
-  bool isFileAllocationBeingExecuted() const
-  {
-    return _currentFileAllocationEntry.get() != 0;
-  }
+  bool isFileAllocationBeingExecuted() const;
 
 
-  FileAllocationEntryHandle getCurrentFileAllocationEntry()
-  {
-    return _currentFileAllocationEntry;
-  }
+  FileAllocationEntryHandle getCurrentFileAllocationEntry();
 
 
-  void markCurrentFileAllocationEntryDone()
-  {
-    _currentFileAllocationEntry = 0;
-  }
+  void markCurrentFileAllocationEntryDone();
 
 
-  bool nextFileAllocationEntryExists() const
-  {
-    return !_fileAllocationEntries.empty();
-  }
+  bool nextFileAllocationEntryExists() const;
 
 
-  FileAllocationEntryHandle popNextFileAllocationEntry()
-  {
-    if(!nextFileAllocationEntryExists()) {
-      return 0;
-    }
-    FileAllocationEntryHandle entry = _fileAllocationEntries.front();
-    _fileAllocationEntries.pop_front();
-    _currentFileAllocationEntry = entry;
-    return entry;
-  }
+  FileAllocationEntryHandle popNextFileAllocationEntry();
 
 
-  void pushFileAllocationEntry(const FileAllocationEntryHandle& entry)
-  {
-    _fileAllocationEntries.push_back(entry);
-  }
+  void pushFileAllocationEntry(const FileAllocationEntryHandle& entry);
 
 
-  int32_t countFileAllocationEntryInQueue() const
-  {
-    return _fileAllocationEntries.size();
-  }
+  int32_t countFileAllocationEntryInQueue() const;
 };
 };
 
 
 typedef SharedHandle<FileAllocationMan> FileAllocationManHandle;
 typedef SharedHandle<FileAllocationMan> FileAllocationManHandle;

+ 14 - 1
src/FileEntry.cc

@@ -45,7 +45,8 @@ FileEntry::FileEntry(const string& path,
 
 
 FileEntry::~FileEntry() {}
 FileEntry::~FileEntry() {}
 
 
-void FileEntry::setupDir(const string& parentDir) {
+void FileEntry::setupDir(const string& parentDir)
+{
   string absPath = parentDir+"/"+path;
   string absPath = parentDir+"/"+path;
   char* temp = strdup(absPath.c_str());
   char* temp = strdup(absPath.c_str());
   string dir = string(dirname(temp));
   string dir = string(dirname(temp));
@@ -62,3 +63,15 @@ void FileEntry::setupDir(const string& parentDir) {
     throw new DlAbortEx("Failed to create directory %s.", dir.c_str());
     throw new DlAbortEx("Failed to create directory %s.", dir.c_str());
   }  
   }  
 }
 }
+
+FileEntry& FileEntry::operator=(const FileEntry& entry)
+{
+  if(this != &entry) {
+    path = entry.path;
+    length = entry.length;
+    offset = entry.offset;
+    extracted = entry.extracted;
+    requested = entry.requested;
+  }
+  return *this;
+}

+ 2 - 12
src/FileEntry.h

@@ -50,20 +50,10 @@ public:
 
 
   FileEntry(const string& path, int64_t length, int64_t offset);
   FileEntry(const string& path, int64_t length, int64_t offset);
 
 
-  FileEntry& operator=(const FileEntry& entry)
-  {
-    if(this != &entry) {
-      path = entry.path;
-      length = entry.length;
-      offset = entry.offset;
-      extracted = entry.extracted;
-      requested = entry.requested;
-    }
-    return *this;
-  }
-
   ~FileEntry();
   ~FileEntry();
 
 
+  FileEntry& operator=(const FileEntry& entry);
+
   string getBasename() const
   string getBasename() const
   {
   {
     return File(path).getBasename();
     return File(path).getBasename();

+ 24 - 2
src/FillRequestGroupCommand.cc

@@ -33,11 +33,33 @@
  */
  */
 /* copyright --> */
 /* copyright --> */
 #include "FillRequestGroupCommand.h"
 #include "FillRequestGroupCommand.h"
+#include "DownloadEngine.h"
+#include "RequestGroupMan.h"
+#include "RequestGroup.h"
+#include "DlAbortEx.h"
+#include "message.h"
+
+FillRequestGroupCommand::FillRequestGroupCommand(int32_t cuid,
+						 DownloadEngine* e,
+						 int32_t interval):
+  Command(cuid),
+  _e(e),
+  _interval(interval)
+{
+  setStatusRealtime();
+}
+
+FillRequestGroupCommand::~FillRequestGroupCommand() {}
 
 
 bool FillRequestGroupCommand::execute()
 bool FillRequestGroupCommand::execute()
 {
 {
-  _e->_requestGroupMan->fillRequestGroupFromReserver(_e);
-  if(_e->_requestGroupMan->downloadFinished()) {
+  try {
+    _e->_requestGroupMan->fillRequestGroupFromReserver(_e);
+  } catch(DlAbortEx* ex) {
+    logger->error(EX_EXCEPTION_CAUGHT, ex);
+    delete ex;
+  }
+  if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
     return true;
     return true;
   }
   }
   _e->commands.push_back(this);
   _e->commands.push_back(this);

+ 8 - 9
src/FillRequestGroupCommand.h

@@ -37,8 +37,11 @@
 
 
 #include "Command.h"
 #include "Command.h"
 #include "TimeA2.h"
 #include "TimeA2.h"
-#include "RequestGroup.h"
-#include "DownloadEngine.h"
+
+class RequestGroup;
+extern typedef SharedHandle<RequestGroup> RequestGroupHandle;
+extern typedef deque<RequestGroupHandle> RequestGroups;
+class DownloadEngine;
 
 
 class FillRequestGroupCommand : public Command {
 class FillRequestGroupCommand : public Command {
 private:
 private:
@@ -47,13 +50,9 @@ private:
   int32_t _interval;
   int32_t _interval;
   Time _checkPoint;
   Time _checkPoint;
 public:
 public:
-  FillRequestGroupCommand(int cuid, DownloadEngine* e, int32_t interval):
-    Command(cuid),
-    _e(e),
-    _interval(interval)
-  {
-    setStatusRealtime();
-  }
+  FillRequestGroupCommand(int32_t cuid, DownloadEngine* e, int32_t interval);
+
+  virtual ~FillRequestGroupCommand();
 
 
   virtual bool execute();
   virtual bool execute();
 
 

Some files were not shown because too many files changed in this diff