Browse Source

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

	Don't connect server before checking file integrity at startup, 
if
	filesize and output file path are known.
	* src/AbstractCommand.cc
	* src/StreamFileAllocationEntry.cc
	* src/Metalink2RequestGroup.cc
	* src/RequestGroup.{h, cc}
	* src/HttpResponseCommand.cc
	* src/FtpNegotiationCommand.cc

	Added DownloadFailureException. If it is thrown, RequestGroup 
should
	halt.
	* src/AbstractCommand.cc
	* src/DownloadFailureException.h
	* src/RequestGroup.cc

	Catch RecoverableException, instead of DlAbortEx.
	* src/RequestGroupMan.cc
	* src/FillRequestGroupCommand.cc
	* src/MetaFileUtil.cc
	* src/IteratableChunkChecksumValidator.cc

	Now first parameter of MSG_DOWNLOAD_ABORTED is 
gid(RequestGroup::
	getGID())
	* src/CheckIntegrityCommand.cc
	* src/message.h
	
	Print gid instead of idx.
	* src/RequestGroupMan.cc

	Removed exception throwers declaration.
	* src/DirectDiskAdaptor.{h, cc}
	* src/SocketCore.{h, cc}
	* src/MultiDiskAdaptor.{h, cc}
	* src/HttpConnection.{h, cc}
	* src/HttpResponse.{h, cc}
	* src/DiskAdaptor.{h, cc}
	* src/CopyDiskAdaptor.{h, cc}
	* src/MultiDiskAdaptor.{h, cc}
	* src/HttpHeaderProcessor.{h, cc}
	* src/AbstractSingleDiskAdaptor.{h, cc}
	* src/Util.{h, cc}
	* test/UtilTest.cc
	* src/DefaultDiskWriter.{h, cc}
	* src/FtpConnection.{h, cc}
	* src/AbstractDiskWriter.{h, cc}

	Removed duplicate code.
	* src/StreamCheckIntegrityEntry.cc

	Removed unnecessary include.
	* src/DiskWriter.h

	Included Exception.h
	* src/option_processing.cc

	Included 2 files and added doc
	* src/TrackerWatcherCommand.cc

	* src/SocketCore.cc (writeData): Fixed send error with GnuTLS.
Tatsuhiro Tsujikawa 18 years ago
parent
commit
b5ad009809
48 changed files with 449 additions and 384 deletions
  1. 62 0
      ChangeLog
  2. 7 2
      TODO
  3. 5 133
      src/AbstractCommand.cc
  4. 1 8
      src/AbstractDiskWriter.cc
  5. 8 9
      src/AbstractDiskWriter.h
  6. 0 5
      src/AbstractSingleDiskAdaptor.cc
  7. 7 8
      src/AbstractSingleDiskAdaptor.h
  8. 2 1
      src/CheckIntegrityCommand.cc
  9. 0 2
      src/CopyDiskAdaptor.cc
  10. 2 3
      src/CopyDiskAdaptor.h
  11. 0 1
      src/DefaultDiskWriter.cc
  12. 1 3
      src/DefaultDiskWriter.h
  13. 0 1
      src/DirectDiskAdaptor.cc
  14. 1 2
      src/DirectDiskAdaptor.h
  15. 1 1
      src/DiskAdaptor.cc
  16. 1 3
      src/DiskAdaptor.h
  17. 0 1
      src/DiskWriter.h
  18. 62 0
      src/DownloadFailureException.h
  19. 2 2
      src/FillRequestGroupCommand.cc
  20. 1 13
      src/FtpConnection.cc
  21. 13 15
      src/FtpConnection.h
  22. 9 12
      src/FtpNegotiationCommand.cc
  23. 2 3
      src/HttpConnection.cc
  24. 3 5
      src/HttpConnection.h
  25. 2 4
      src/HttpHeaderProcessor.cc
  26. 4 6
      src/HttpHeaderProcessor.h
  27. 2 1
      src/HttpResponse.cc
  28. 1 3
      src/HttpResponse.h
  29. 20 30
      src/HttpResponseCommand.cc
  30. 2 1
      src/IteratableChunkChecksumValidator.cc
  31. 1 1
      src/MetaFileUtil.cc
  32. 1 1
      src/Metalink2RequestGroup.cc
  33. 1 8
      src/MultiDiskAdaptor.cc
  34. 8 13
      src/MultiDiskAdaptor.h
  35. 0 1
      src/RealtimeCommand.cc
  36. 154 18
      src/RequestGroup.cc
  37. 16 1
      src/RequestGroup.h
  38. 6 6
      src/RequestGroupMan.cc
  39. 3 16
      src/SocketCore.cc
  40. 16 18
      src/SocketCore.h
  41. 4 13
      src/StreamCheckIntegrityEntry.cc
  42. 10 6
      src/StreamFileAllocationEntry.cc
  43. 3 0
      src/TrackerWatcherCommand.cc
  44. 1 1
      src/Util.cc
  45. 1 2
      src/Util.h
  46. 1 1
      src/message.h
  47. 1 0
      src/option_processing.cc
  48. 1 0
      test/UtilTest.cc

+ 62 - 0
ChangeLog

@@ -1,3 +1,65 @@
+2007-11-10  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	Don't connect server before checking file integrity at startup, if
+	filesize and output file path are known.
+	* src/AbstractCommand.cc
+	* src/StreamFileAllocationEntry.cc
+	* src/Metalink2RequestGroup.cc
+	* src/RequestGroup.{h, cc}
+	* src/HttpResponseCommand.cc
+	* src/FtpNegotiationCommand.cc
+
+	Added DownloadFailureException. If it is thrown, RequestGroup should
+	halt.
+	* src/AbstractCommand.cc
+	* src/DownloadFailureException.h
+	* src/RequestGroup.cc
+
+	Catch RecoverableException, instead of DlAbortEx.
+	* src/RequestGroupMan.cc
+	* src/FillRequestGroupCommand.cc
+	* src/MetaFileUtil.cc
+	* src/IteratableChunkChecksumValidator.cc
+
+	Now first parameter of MSG_DOWNLOAD_ABORTED is gid(RequestGroup::
+	getGID())
+	* src/CheckIntegrityCommand.cc
+	* src/message.h
+	
+	Print gid instead of idx.
+	* src/RequestGroupMan.cc
+
+	Removed exception throwers declaration.
+	* src/DirectDiskAdaptor.{h, cc}
+	* src/SocketCore.{h, cc}
+	* src/MultiDiskAdaptor.{h, cc}
+	* src/HttpConnection.{h, cc}
+	* src/HttpResponse.{h, cc}
+	* src/DiskAdaptor.{h, cc}
+	* src/CopyDiskAdaptor.{h, cc}
+	* src/MultiDiskAdaptor.{h, cc}
+	* src/HttpHeaderProcessor.{h, cc}
+	* src/AbstractSingleDiskAdaptor.{h, cc}
+	* src/Util.{h, cc}
+	* test/UtilTest.cc
+	* src/DefaultDiskWriter.{h, cc}
+	* src/FtpConnection.{h, cc}
+	* src/AbstractDiskWriter.{h, cc}
+
+	Removed duplicate code.
+	* src/StreamCheckIntegrityEntry.cc
+
+	Removed unnecessary include.
+	* src/DiskWriter.h
+
+	Included Exception.h
+	* src/option_processing.cc
+
+	Included 2 files and added doc
+	* src/TrackerWatcherCommand.cc
+
+	* src/SocketCore.cc (writeData): Fixed send error with GnuTLS.
+
 2007-11-08  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 	
 	Changed CheckIntegrityEntry interface so that it can define

+ 7 - 2
TODO

@@ -48,10 +48,15 @@
 * Implement the feature to treat http/ftp as auxuality download method for BitTorrent
 * http-seeding(single and multi-file torrent)
 * Use content-type for PostDownloadHandler
+* Rewrite exception usage:
+  RecoverableException
+    DlRetryEx .... Retry using same connection/url. Should be renamed to TemporaryFailureException
+    DlAbortEx .... Abort download with the connection/url. Should be renamed to PermanentFailureException
+    DownloadFailureException .... RequestGroup should halt.
+  FatalException .... Program should abort.
 
 -- remaining features to be implemented for 0.12.0 release
 * Reimplement ChecksumCommand(validation using 1 checksum for 1 file)
 * Implement duplicate download checking in Bt
 * improve --metalink-location field
-* Do not connect a server when before checking file integrity.
-* If size and filename is provided(for example, metalink), "HEAD" like behavior is unnecessary.
+* Piece length conversion when loading file

+ 5 - 133
src/AbstractCommand.cc

@@ -38,25 +38,18 @@
 #include "CUIDCounter.h"
 #include "DlAbortEx.h"
 #include "DlRetryEx.h"
-#include "FatalException.h"
+#include "DownloadFailureException.h"
 #include "InitiateConnectionCommandFactory.h"
 #include "Util.h"
 #include "message.h"
 #include "SleepCommand.h"
 #include "prefs.h"
 #include "DNSCache.h"
-#include "SingleFileDownloadContext.h"
-#include "DefaultPieceStorage.h"
-#include "UnknownLengthPieceStorage.h"
-#include "File.h"
 #include "StreamCheckIntegrityEntry.h"
-#include "BtProgressInfoFile.h"
-#include "CheckIntegrityCommand.h"
-#include "DiskAdaptor.h"
 #include "PeerStat.h"
 #include "Segment.h"
-#include "DiskWriterFactory.h"
 #include "Option.h"
+#include "PieceStorage.h"
 
 AbstractCommand::AbstractCommand(int32_t cuid,
 				 const RequestHandle& req,
@@ -158,7 +151,8 @@ bool AbstractCommand::execute() {
       delete(err);
       return prepareForRetry(e->option->getAsInt(PREF_RETRY_WAIT));
     }
-  } catch(FatalException* err) {
+  } catch(DownloadFailureException* err) {
+    logger->error(EX_EXCEPTION_CAUGHT, err);
     delete(err);
     _requestGroup->setHaltRequested(true);
     return true;
@@ -300,131 +294,9 @@ bool AbstractCommand::nameResolveFinished() const {
 }
 #endif // ENABLE_ASYNC_DNS
 
-void AbstractCommand::loadAndOpenFile(const BtProgressInfoFileHandle& progressInfoFile)
-{
-  if(!_requestGroup->isPreLocalFileCheckEnabled()) {
-    _requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
-    return;
-  }
-
-  //_requestGroup->setProgressInfoFile(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()
-{
-  // 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->onDownloadIncomplete(e));
-    }
+  e->addCommand(_requestGroup->processCheckIntegrityEntry(entry, e));
 }

+ 1 - 8
src/AbstractDiskWriter.cc

@@ -38,6 +38,7 @@
 #include "message.h"
 #include "LogFactory.h"
 #include "a2io.h"
+#include "DlAbortEx.h"
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -55,7 +56,6 @@ AbstractDiskWriter::~AbstractDiskWriter()
 }
 
 void AbstractDiskWriter::openFile(const string& filename, int64_t totalLength)
-  throw(DlAbortEx*)
 {
   File f(filename);
   if(f.exists()) {
@@ -75,7 +75,6 @@ void AbstractDiskWriter::closeFile()
 
 void AbstractDiskWriter::openExistingFile(const string& filename,
 					  int64_t totalLength)
-  throw(DlAbortEx*)
 {
   this->filename = filename;
   File f(filename);
@@ -89,7 +88,6 @@ void AbstractDiskWriter::openExistingFile(const string& filename,
 }
 
 void AbstractDiskWriter::createFile(const string& filename, int32_t addFlags)
-  throw(DlAbortEx*)
 {
   this->filename = filename;
   assert(filename.size());
@@ -110,7 +108,6 @@ int32_t AbstractDiskWriter::readDataInternal(unsigned char* data, int32_t len)
 }
 
 void AbstractDiskWriter::seek(int64_t offset)
-  throw(DlAbortEx*)
 {
   if(offset != lseek(fd, offset, SEEK_SET)) {
     throw new DlAbortEx(EX_FILE_SEEK, filename.c_str(), strerror(errno));
@@ -118,7 +115,6 @@ void AbstractDiskWriter::seek(int64_t offset)
 }
 
 void AbstractDiskWriter::writeData(const unsigned char* data, int32_t len, int64_t offset)
-  throw(DlAbortEx*)
 {
   seek(offset);
   if(writeDataInternal(data, len) < 0) {
@@ -127,7 +123,6 @@ void AbstractDiskWriter::writeData(const unsigned char* data, int32_t len, int64
 }
 
 int32_t AbstractDiskWriter::readData(unsigned char* data, int32_t len, int64_t offset)
-  throw(DlAbortEx*)
 {
   int32_t ret;
   seek(offset);
@@ -138,7 +133,6 @@ int32_t AbstractDiskWriter::readData(unsigned char* data, int32_t len, int64_t o
 }
 
 void AbstractDiskWriter::truncate(int64_t length)
-  throw(DlAbortEx*)
 {
   if(fd == -1) {
     throw new DlAbortEx("File not opened.");
@@ -148,7 +142,6 @@ void AbstractDiskWriter::truncate(int64_t length)
 
 // TODO the file descriptor fd must be opened before calling this function.
 int64_t AbstractDiskWriter::size() const
-  throw(DlAbortEx*)
 {
   if(fd == -1) {
     throw new DlAbortEx("File not opened.");

+ 8 - 9
src/AbstractDiskWriter.h

@@ -37,7 +37,6 @@
 
 #include "DiskWriter.h"
 #include "Logger.h"
-#include "DlAbortEx.h"
 
 class AbstractDiskWriter : public DiskWriter {
 protected:
@@ -45,31 +44,31 @@ protected:
   int32_t fd;
   const Logger* logger;
 
-  void createFile(const string& filename, int32_t addFlags = 0) throw(DlAbortEx*);
+  void createFile(const string& filename, int32_t addFlags = 0);
 
 private:
   int32_t writeDataInternal(const unsigned char* data, int32_t len);
   int32_t readDataInternal(unsigned char* data, int32_t len);
 
-  void seek(int64_t offset) throw(DlAbortEx*);
+  void seek(int64_t offset);
 
 public:
   AbstractDiskWriter();
   virtual ~AbstractDiskWriter();
 
-  virtual void openFile(const string& filename, int64_t totalLength = 0) throw(DlAbortEx*);
+  virtual void openFile(const string& filename, int64_t totalLength = 0);
 
   virtual void closeFile();
 
-  virtual void openExistingFile(const string& filename, int64_t totalLength = 0) throw(DlAbortEx*);
+  virtual void openExistingFile(const string& filename, int64_t totalLength = 0);
 
-  virtual void writeData(const unsigned char* data, int32_t len, int64_t offset) throw(DlAbortEx*);
+  virtual void writeData(const 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 int32_t readData(unsigned char* data, int32_t len, int64_t offset);
 
-  virtual void truncate(int64_t length) throw(DlAbortEx*);
+  virtual void truncate(int64_t length);
 
-  virtual int64_t size() const throw(DlAbortEx*);
+  virtual int64_t size() const;
 };
 
 #endif // _D_ABSTRACT_DISK_WRITER_H_

+ 0 - 5
src/AbstractSingleDiskAdaptor.cc

@@ -37,13 +37,11 @@
 #include "SingleFileAllocationIterator.h"
 
 void AbstractSingleDiskAdaptor::initAndOpenFile()
-  throw(DlAbortEx*)
 {
   diskWriter->initAndOpenFile(getFilePath(), totalLength);
 }
 
 void AbstractSingleDiskAdaptor::openFile()
-  throw(DlAbortEx*)
 {
   diskWriter->openFile(getFilePath(), totalLength);
 }
@@ -54,19 +52,16 @@ void AbstractSingleDiskAdaptor::closeFile()
 }
 
 void AbstractSingleDiskAdaptor::openExistingFile()
-  throw(DlAbortEx*)
 {
   diskWriter->openExistingFile(getFilePath(), totalLength);
 }
 
 void AbstractSingleDiskAdaptor::writeData(const unsigned char* data, int32_t len, int64_t offset)
-  throw(DlAbortEx*)
 {
   diskWriter->writeData(data, len, offset);
 }
 
 int32_t AbstractSingleDiskAdaptor::readData(unsigned char* data, int32_t len, int64_t offset)
-  throw(DlAbortEx*)
 {
   return diskWriter->readData(data, len, offset);
 }

+ 7 - 8
src/AbstractSingleDiskAdaptor.h

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

+ 2 - 1
src/CheckIntegrityCommand.cc

@@ -64,7 +64,8 @@ bool CheckIntegrityCommand::executeInternal()
   if(_entry->finished()) {
     _entry->updatePieceStorage();
     if(_requestGroup->downloadFinished()) {
-      logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, cuid, _requestGroup->getFilePath().c_str());
+      logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, _requestGroup->getGID(),
+		     _requestGroup->getFilePath().c_str());
       _e->addCommand(_entry->onDownloadFinished(_e));
     } else {
       _e->addCommand(_entry->onDownloadIncomplete(_e));

+ 0 - 2
src/CopyDiskAdaptor.cc

@@ -37,7 +37,6 @@
 #include "message.h"
 
 void CopyDiskAdaptor::onDownloadComplete()
-  throw(DlAbortEx*)
 {
   closeFile();
   fixFilename();
@@ -45,7 +44,6 @@ void CopyDiskAdaptor::onDownloadComplete()
 }
 
 void CopyDiskAdaptor::fixFilename()
-  throw(DlAbortEx*)
 {
   int64_t offset = 0;
   for(FileEntries::iterator itr = fileEntries.begin();

+ 2 - 3
src/CopyDiskAdaptor.h

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

+ 0 - 1
src/DefaultDiskWriter.cc

@@ -45,7 +45,6 @@ DefaultDiskWriter::~DefaultDiskWriter() {}
 
 void DefaultDiskWriter::initAndOpenFile(const string& filename,
 					int64_t totalLength)
-  throw(DlAbortEx*)
 {
   createFile(filename);
 }

+ 1 - 3
src/DefaultDiskWriter.h

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

+ 0 - 1
src/DirectDiskAdaptor.cc

@@ -40,7 +40,6 @@ string DirectDiskAdaptor::getFilePath()
 }
 
 void DirectDiskAdaptor::onDownloadComplete()
-  throw(DlAbortEx*)
 {
   closeFile();
   openFile();

+ 1 - 2
src/DirectDiskAdaptor.h

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

+ 1 - 1
src/DiskAdaptor.cc

@@ -35,13 +35,13 @@
 #include "DiskAdaptor.h"
 #include "LogFactory.h"
 #include "message.h"
+#include "DlAbortEx.h"
 
 DiskAdaptor::DiskAdaptor():logger(LogFactory::getInstance()) {}
 
 DiskAdaptor::~DiskAdaptor() {}
 
 FileEntryHandle DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) const
-  throw(DlAbortEx*)
 {
   for(FileEntries::const_iterator itr = fileEntries.begin();
       itr != fileEntries.end(); itr++) {

+ 1 - 3
src/DiskAdaptor.h

@@ -39,7 +39,6 @@
 #include "FileEntry.h"
 #include "Logger.h"
 #include "FileAllocationIterator.h"
-#include "DlAbortEx.h"
 
 class DiskAdaptor:public BinaryStream {
 protected:
@@ -73,8 +72,7 @@ public:
     this->fileEntries = fileEntries;
   }
 
-  FileEntryHandle
-  getFileEntryFromPath(const string& fileEntryPath) const throw(DlAbortEx*);
+  FileEntryHandle getFileEntryFromPath(const string& fileEntryPath) const;
 
   const FileEntries& getFileEntries() const { return fileEntries; }
 

+ 0 - 1
src/DiskWriter.h

@@ -36,7 +36,6 @@
 #define _D_DISK_WRITER_H_
 
 #include "BinaryStream.h"
-#include "DlAbortEx.h"
 
 /**
  * Interface for writing to a binary stream of bytes.

+ 62 - 0
src/DownloadFailureException.h

@@ -0,0 +1,62 @@
+/* <!-- 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_FAILURE_EXCEPTION_H_
+#define _D_DOWNLOAD_FAILURE_EXCEPTION_H_
+#include "RecoverableException.h"
+
+/**
+ * Throw this exception when a RequestGroup should aborted.
+ * FYI, DlAbortEx is the exception to abort 1 Request.
+ */
+class DownloadFailureException : public RecoverableException {
+public:
+  DownloadFailureException(Exception* cause = 0):RecoverableException(cause) {}
+
+  DownloadFailureException(const char* msg, ...) {
+    va_list ap;
+    va_start(ap, msg);
+    setMsg(string(msg), ap);
+    va_end(ap);
+  }
+
+  DownloadFailureException(Exception* cause, const char* msg, ...):RecoverableException(cause) {
+    va_list ap;
+    va_start(ap, msg);
+    setMsg(string(msg), ap);
+    va_end(ap);
+  }
+};
+
+#endif // _D_DOWNLOAD_FAILURE_EXCEPTION_H_

+ 2 - 2
src/FillRequestGroupCommand.cc

@@ -36,7 +36,7 @@
 #include "DownloadEngine.h"
 #include "RequestGroupMan.h"
 #include "RequestGroup.h"
-#include "DlAbortEx.h"
+#include "RecoverableException.h"
 #include "message.h"
 
 FillRequestGroupCommand::FillRequestGroupCommand(int32_t cuid,
@@ -55,7 +55,7 @@ bool FillRequestGroupCommand::execute()
 {
   try {
     _e->_requestGroupMan->fillRequestGroupFromReserver(_e);
-  } catch(DlAbortEx* ex) {
+  } catch(RecoverableException* ex) {
     logger->error(EX_EXCEPTION_CAUGHT, ex);
     delete ex;
   }

+ 1 - 13
src/FtpConnection.cc

@@ -39,6 +39,7 @@
 #include "LogFactory.h"
 #include "AuthConfigFactory.h"
 #include "AuthConfig.h"
+#include "DlRetryEx.h"
 
 FtpConnection::FtpConnection(int32_t cuid, const SocketHandle& socket,
 			     const RequestHandle req, const Option* op)
@@ -49,7 +50,6 @@ FtpConnection::FtpConnection(int32_t cuid, const SocketHandle& socket,
 FtpConnection::~FtpConnection() {}
 
 void FtpConnection::sendUser() const
-  throw(DlRetryEx*)
 {
   string request = "USER "+AuthConfigFactorySingleton::instance()->createAuthConfig(req)->getUser()+"\r\n";
   logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
@@ -57,7 +57,6 @@ void FtpConnection::sendUser() const
 }
 
 void FtpConnection::sendPass() const
-  throw(DlRetryEx*)
 {
   string request = "PASS "+AuthConfigFactorySingleton::instance()->createAuthConfig(req)->getPassword()+"\r\n";
   logger->info(MSG_SENDING_REQUEST, cuid, "PASS ********");
@@ -65,7 +64,6 @@ void FtpConnection::sendPass() const
 }
 
 void FtpConnection::sendType() const
-  throw(DlRetryEx*)
 {
   string type;
   if(option->get(PREF_FTP_TYPE) == V_ASCII) {
@@ -79,7 +77,6 @@ void FtpConnection::sendType() const
 }
 
 void FtpConnection::sendCwd() const
-  throw(DlRetryEx*)
 {
   string request = "CWD "+Util::urldecode(req->getDir())+"\r\n";
   logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
@@ -87,7 +84,6 @@ void FtpConnection::sendCwd() const
 }
 
 void FtpConnection::sendSize() const
-  throw(DlRetryEx*)
 {
   string request = "SIZE "+Util::urldecode(req->getFile())+"\r\n";
   logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
@@ -95,7 +91,6 @@ void FtpConnection::sendSize() const
 }
 
 void FtpConnection::sendPasv() const
-  throw(DlRetryEx*)
 {
   string request = "PASV\r\n";
   logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
@@ -103,7 +98,6 @@ void FtpConnection::sendPasv() const
 }
 
 SocketHandle FtpConnection::sendPort() const
-  throw(DlAbortEx*, DlRetryEx*)
 {
   SocketHandle serverSocket;
   serverSocket->beginListen();
@@ -124,7 +118,6 @@ SocketHandle FtpConnection::sendPort() const
 }
 
 void FtpConnection::sendRest(const SegmentHandle& segment) const
-  throw(DlRetryEx*)
 {
   string request = "REST "+Util::llitos(segment->getPositionToWrite())+"\r\n";
   logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
@@ -132,7 +125,6 @@ void FtpConnection::sendRest(const SegmentHandle& segment) const
 }
 
 void FtpConnection::sendRetr() const
-  throw(DlRetryEx*)
 {
   string request = "RETR "+Util::urldecode(req->getFile())+"\r\n";
   logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
@@ -177,7 +169,6 @@ bool FtpConnection::isEndOfResponse(int32_t status, const string& response) cons
 }
 
 bool FtpConnection::bulkReceiveResponse(pair<int32_t, string>& response)
-  throw(DlRetryEx*)
 {
   char buf[1024];  
   while(socket->isReadable(0)) {
@@ -211,7 +202,6 @@ bool FtpConnection::bulkReceiveResponse(pair<int32_t, string>& response)
 }
 
 int32_t FtpConnection::receiveResponse()
-  throw(DlRetryEx*)
 {
   pair<int32_t, string> response;
   if(bulkReceiveResponse(response)) {
@@ -222,7 +212,6 @@ int32_t FtpConnection::receiveResponse()
 }
 
 int32_t FtpConnection::receiveSizeResponse(int64_t& size)
-  throw(DlRetryEx*)
 {
   pair<int32_t, string> response;
   if(bulkReceiveResponse(response)) {
@@ -236,7 +225,6 @@ int32_t FtpConnection::receiveSizeResponse(int64_t& size)
 }
 
 int32_t FtpConnection::receivePasvResponse(pair<string, int32_t>& dest)
-  throw(DlRetryEx*)
 {
   pair<int32_t, string> response;
   if(bulkReceiveResponse(response)) {

+ 13 - 15
src/FtpConnection.h

@@ -41,8 +41,6 @@
 #include "Logger.h"
 #include "Segment.h"
 #include "Request.h"
-#include "DlAbortEx.h"
-#include "DlRetryEx.h"
 #include <utility>
 
 class FtpConnection {
@@ -57,24 +55,24 @@ private:
 
   int32_t getStatus(const string& response) const;
   bool isEndOfResponse(int32_t status, const string& response) const;
-  bool bulkReceiveResponse(pair<int32_t, string>& response) throw(DlRetryEx*);
+  bool bulkReceiveResponse(pair<int32_t, string>& response);
 public:
   FtpConnection(int32_t cuid, const SocketHandle& socket,
 		const RequestHandle req, const Option* op);
   ~FtpConnection();
-  void sendUser() const throw(DlRetryEx*);
-  void sendPass() const throw(DlRetryEx*);
-  void sendType() const throw(DlRetryEx*);
-  void sendCwd() const throw(DlRetryEx*);
-  void sendSize() const throw(DlRetryEx*);
-  void sendPasv() const throw(DlRetryEx*);
-  SocketHandle sendPort() const throw(DlAbortEx*, DlRetryEx*);
-  void sendRest(const SegmentHandle& segment) const throw(DlRetryEx*);
-  void sendRetr() const throw(DlRetryEx*);
+  void sendUser() const;
+  void sendPass() const;
+  void sendType() const;
+  void sendCwd() const;
+  void sendSize() const;
+  void sendPasv() const;
+  SocketHandle sendPort() const;
+  void sendRest(const SegmentHandle& segment) const;
+  void sendRetr() const;
 
-  int32_t receiveResponse() throw(DlRetryEx*);
-  int32_t receiveSizeResponse(int64_t& size) throw(DlRetryEx*);
-  int32_t receivePasvResponse(pair<string, int32_t>& dest) throw(DlRetryEx*);
+  int32_t receiveResponse();
+  int32_t receiveSizeResponse(int64_t& size);
+  int32_t receivePasvResponse(pair<string, int32_t>& dest);
 };
 
 #endif // _D_FTP_CONNECTION_H_

+ 9 - 12
src/FtpNegotiationCommand.cc

@@ -195,29 +195,26 @@ bool FtpNegotiationCommand::recvSize() {
     throw new DlAbortEx(EX_TOO_LARGE_FILE, Util::llitos(size, true).c_str());
   }
   if(_requestGroup->getPieceStorage().isNull()) {
-    SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setTotalLength(size);
-    SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setFilename(Util::urldecode(req->getFile()));
+    SingleFileDownloadContextHandle dctx = _requestGroup->getDownloadContext();
+    dctx->setTotalLength(size);
+    dctx->setFilename(Util::urldecode(req->getFile()));
 
-    initPieceStorage();
+    _requestGroup->initPieceStorage();
 
-    // TODO validate totalsize against hintTotalSize if it is provided.
+    // validate totalsize against hintTotalSize if it is provided.
     _requestGroup->validateTotalLengthByHint(size);
     // TODO Is this really necessary?
     if(req->getMethod() == Request::METHOD_HEAD) {
-      // TODO because we don't want segment file to be saved.
       sequence = SEQ_HEAD_OK;
       return false;
     }
 
     BtProgressInfoFileHandle infoFile = new DefaultBtProgressInfoFile(_requestGroup->getDownloadContext(), _requestGroup->getPieceStorage(), e->option);
-    if(e->option->get(PREF_CHECK_INTEGRITY) != V_TRUE) {
-      if(!infoFile->exists() && downloadFinishedByFileLength()) {
-	logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, cuid, _requestGroup->getFilePath().c_str());
-	sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED;
-	return false;
-      }
+    if(!infoFile->exists() && _requestGroup->downloadFinishedByFileLength()) {
+      sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED;
+      return false;
     }
-    loadAndOpenFile(infoFile);
+    _requestGroup->loadAndOpenFile(infoFile);
     prepareForNextAction();
     
     sequence = SEQ_FILE_PREPARATION;

+ 2 - 3
src/HttpConnection.cc

@@ -37,6 +37,8 @@
 #include "message.h"
 #include "prefs.h"
 #include "LogFactory.h"
+#include "DlRetryEx.h"
+#include "DlAbortEx.h"
 #include <sstream>
 
 HttpConnection::HttpConnection(int32_t cuid,
@@ -63,7 +65,6 @@ string HttpConnection::eraseConfidentialInfo(const string& request)
 }
 
 void HttpConnection::sendRequest(const HttpRequestHandle& httpRequest)
-  throw(DlRetryEx*)
 {
   string request = httpRequest->createRequest();
   logger->info(MSG_SENDING_REQUEST, cuid, eraseConfidentialInfo(request).c_str());
@@ -73,7 +74,6 @@ void HttpConnection::sendRequest(const HttpRequestHandle& httpRequest)
 }
 
 void HttpConnection::sendProxyRequest(const HttpRequestHandle& httpRequest)
-  throw(DlRetryEx*)
 {
   string request = httpRequest->createProxyRequest();
   logger->info(MSG_SENDING_REQUEST, cuid, eraseConfidentialInfo(request).c_str());
@@ -83,7 +83,6 @@ void HttpConnection::sendProxyRequest(const HttpRequestHandle& httpRequest)
 }
 
 HttpResponseHandle HttpConnection::receiveResponse()
-  throw(DlAbortEx*, DlRetryEx*)
 {
   if(outstandingHttpRequests.size() == 0) {
     throw new DlAbortEx(EX_NO_HTTP_REQUEST_ENTRY_FOUND);

+ 3 - 5
src/HttpConnection.h

@@ -44,8 +44,6 @@
 #include "Logger.h"
 #include "HttpResponse.h"
 #include "HttpHeaderProcessor.h"
-#include "DlRetryEx.h"
-#include "DlAbortEx.h"
 
 class HttpRequestEntry {
 private:
@@ -95,12 +93,12 @@ public:
    * HTTP proxy(GET method).
    * @param segment indicates starting postion of the file for downloading
    */
-  void sendRequest(const HttpRequestHandle& httpRequest) throw(DlRetryEx*);
+  void sendRequest(const HttpRequestHandle& httpRequest);
 
   /**
    * Sends Http proxy request using CONNECT method.
    */
-  void sendProxyRequest(const HttpRequestHandle& httpRequest) throw(DlRetryEx*);
+  void sendProxyRequest(const HttpRequestHandle& httpRequest);
 
   /**
    * Receives HTTP response from the server and returns HttpResponseHandle
@@ -113,7 +111,7 @@ public:
    * 
    * @return HttpResponse or 0 if whole response header is not received
    */
-  HttpResponseHandle receiveResponse() throw(DlAbortEx*, DlRetryEx*);
+  HttpResponseHandle receiveResponse();
 
   HttpRequestHandle getFirstHttpRequest() const
   {

+ 2 - 4
src/HttpHeaderProcessor.cc

@@ -35,23 +35,22 @@
 #include "HttpHeaderProcessor.h"
 #include "message.h"
 #include "Util.h"
+#include "DlRetryEx.h"
+#include "DlAbortEx.h"
 
 void HttpHeaderProcessor::update(const char* data, int32_t length)
-  throw(DlAbortEx*)
 {
   checkHeaderLimit(length);
   strm.write(data, length);
 }
 
 void HttpHeaderProcessor::update(const string& data)
-  throw(DlAbortEx*)
 {
   checkHeaderLimit(data.size());
   strm << data;
 }
 
 void HttpHeaderProcessor::checkHeaderLimit(int32_t incomingLength)
-  throw(DlAbortEx*)
 {
   strm.seekg(0, ios::end);
   if((int32_t)strm.tellg()+incomingLength > _limit) {
@@ -88,7 +87,6 @@ void HttpHeaderProcessor::clear()
 }
 
 pair<string, HttpHeaderHandle> HttpHeaderProcessor::getHttpStatusHeader()
-  throw(DlRetryEx*)
 {
   strm.seekg(0, ios::beg);
   string line;

+ 4 - 6
src/HttpHeaderProcessor.h

@@ -37,8 +37,6 @@
 
 #include "common.h"
 #include "HttpHeader.h"
-#include "DlRetryEx.h"
-#include "DlAbortEx.h"
 #include <utility>
 #include <sstream>
 
@@ -47,16 +45,16 @@ private:
   stringstream strm;
   int32_t _limit;
 
-  void checkHeaderLimit(int32_t incomingLength) throw(DlAbortEx*);
+  void checkHeaderLimit(int32_t incomingLength);
 
 public:
   HttpHeaderProcessor():_limit(4096) {}
 
   ~HttpHeaderProcessor() {}
 
-  void update(const char* data, int32_t length) throw(DlAbortEx*);
+  void update(const char* data, int32_t length);
 
-  void update(const string& data) throw(DlAbortEx*);
+  void update(const string& data);
 
   /**
    * Returns true if end of header is reached.
@@ -68,7 +66,7 @@ public:
    */
   int32_t getPutBackDataLength() const;
 
-  pair<string, HttpHeaderHandle> getHttpStatusHeader() throw(DlRetryEx*);
+  pair<string, HttpHeaderHandle> getHttpStatusHeader();
 
   string getHeaderString() const;
 

+ 2 - 1
src/HttpResponse.cc

@@ -36,9 +36,10 @@
 #include "ChunkedEncoding.h"
 #include "Util.h"
 #include "message.h"
+#include "DlAbortEx.h"
+#include "DlRetryEx.h"
 
 void HttpResponse::validateResponse() const
-  throw(DlAbortEx*, DlRetryEx*)
 {
   if(status == 401) {
     throw new DlAbortEx(EX_AUTH_FAILED);

+ 1 - 3
src/HttpResponse.h

@@ -40,8 +40,6 @@
 #include "HttpHeader.h"
 #include "TransferEncoding.h"
 #include "LogFactory.h"
-#include "DlAbortEx.h"
-#include "DlRetryEx.h"
 
 class HttpResponse {
 private:
@@ -60,7 +58,7 @@ public:
   
   ~HttpResponse() {}
 
-  void validateResponse() const throw(DlAbortEx*, DlRetryEx*);
+  void validateResponse() const;
 
   /**
    * Returns filename.

+ 20 - 30
src/HttpResponseCommand.cc

@@ -84,35 +84,32 @@ bool HttpResponseCommand::executeInternal()
     e->noWait = true;
     return prepareForRetry(0);
   }
-  if(!_requestGroup->getPieceStorage().isNull()) {
-    // validate totalsize
-    _requestGroup->validateTotalLength(httpResponse->getEntityLength());
-
-    e->commands.push_back(createHttpDownloadCommand(httpResponse));
-    return true;
-  } else {
+  if(_requestGroup->getPieceStorage().isNull()) {
     // validate totalsize against hintTotalSize if it is provided.
-    _requestGroup->validateTotalLengthByHint(httpResponse->getEntityLength());
-
-    SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setFilename(httpResponse->determinFilename());
-    if(httpResponse->isTransferEncodingSpecified()) {
+    int64_t totalLength = httpResponse->getEntityLength();
+    _requestGroup->validateTotalLengthByHint(totalLength);
+    SingleFileDownloadContextHandle dctx = _requestGroup->getDownloadContext();
+    dctx->setTotalLength(totalLength);
+    dctx->setFilename(httpResponse->determinFilename());
+    if(totalLength == 0 || httpResponse->isTransferEncodingSpecified()) {
+      // we ignore content-length when transfer-encoding is set
+      dctx->setTotalLength(0);
       return handleOtherEncoding(httpResponse);
     } else {
       return handleDefaultEncoding(httpResponse);
     }
+  } else {
+    // validate totalsize
+    _requestGroup->validateTotalLength(httpResponse->getEntityLength());
+    e->commands.push_back(createHttpDownloadCommand(httpResponse));
+    return true;
   }
 }
 
 bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpResponse)
 {
   HttpRequestHandle httpRequest = httpResponse->getHttpRequest();
-  int64_t size = httpResponse->getEntityLength();
-  if(size == INT64_MAX || size < 0) {
-    throw new DlAbortEx(EX_TOO_LARGE_FILE, Util::llitos(size, true).c_str());
-  }
-  SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setTotalLength(size);
-
-  initPieceStorage();
+  _requestGroup->initPieceStorage();
 
   // quick hack for method 'head',, is it necessary?
   if(httpRequest->getMethod() == Request::METHOD_HEAD) {
@@ -121,16 +118,13 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpRe
   }
 
   BtProgressInfoFileHandle infoFile = new DefaultBtProgressInfoFile(_requestGroup->getDownloadContext(), _requestGroup->getPieceStorage(), e->option);
-  if(e->option->get(PREF_CHECK_INTEGRITY) != V_TRUE) {
-    if(!infoFile->exists() && downloadFinishedByFileLength()) {
-      logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, cuid, _requestGroup->getFilePath().c_str());
-      return true;
-    }
+  if(!infoFile->exists() && _requestGroup->downloadFinishedByFileLength()) {
+    return true;
   }
 
   DownloadCommand* command = 0;
   try {
-    loadAndOpenFile(infoFile);
+    _requestGroup->loadAndOpenFile(infoFile);
     File file(_requestGroup->getFilePath());
     if(_requestGroup->getRemainingUris().empty() && !file.exists()) {
       command = createHttpDownloadCommand(httpResponse);
@@ -145,7 +139,6 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpRe
 }
 
 bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResponse) {
-  // we ignore content-length when transfer-encoding is set
   HttpRequestHandle httpRequest = httpResponse->getHttpRequest();
   // quick hack for method 'head',, is it necessary?
   if(httpRequest->getMethod() == Request::METHOD_HEAD) {
@@ -153,11 +146,8 @@ bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResp
   }
   // disable keep-alive
   req->setKeepAlive(false);
-
-  initPieceStorage();
-
-  shouldCancelDownloadForSafety();
-  // TODO handle file-size unknown case
+  _requestGroup->initPieceStorage();
+  _requestGroup->shouldCancelDownloadForSafety();
   _requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
   e->commands.push_back(createHttpDownloadCommand(httpResponse));
   return true;

+ 2 - 1
src/IteratableChunkChecksumValidator.cc

@@ -37,6 +37,7 @@
 #include "message.h"
 #include "MessageDigestHelper.h"
 #include "DiskAdaptor.h"
+#include "RecoverableException.h"
 
 void IteratableChunkChecksumValidator::validateChunk()
 {
@@ -44,7 +45,7 @@ void IteratableChunkChecksumValidator::validateChunk()
     string actualChecksum;
     try {
       actualChecksum = calculateActualChecksum();
-    } catch(DlAbortEx* ex) {
+    } catch(RecoverableException* ex) {
       _logger->debug("Caught exception while validating piece index=%d. Some part of file may be missing. Continue operation.", ex, _currentIndex);
       delete ex;
       _bitfield->unsetBit(_currentIndex);

+ 1 - 1
src/MetaFileUtil.cc

@@ -73,7 +73,7 @@ MetaEntry* MetaFileUtil::bdecoding(const char* buf, int32_t len) {
     const char* end = buf+len;
     entry = bdecodingR(&p, end);
     return entry;
-  } catch(DlAbortEx* ex) {
+  } catch(RecoverableException* ex) {
     if(entry != NULL) {
       delete entry;
     }

+ 1 - 1
src/Metalink2RequestGroup.cc

@@ -158,7 +158,7 @@ RequestGroups Metalink2RequestGroup::generate(const string& metalinkFile)
     }
     SingleFileDownloadContextHandle dctx =
       new SingleFileDownloadContext(pieceLength,
-				    0,
+				    entry->getLength(),
 				    "",
 				    entry->file->getPath());
     dctx->setDir(_option->get(PREF_DIR));

+ 1 - 8
src/MultiDiskAdaptor.cc

@@ -38,6 +38,7 @@
 #include "Util.h"
 #include "MultiFileAllocationIterator.h"
 #include "DefaultDiskWriterFactory.h"
+#include "DlAbortEx.h"
 
 void MultiDiskAdaptor::resetDiskWriterEntries()
 {
@@ -60,7 +61,6 @@ string MultiDiskAdaptor::getTopDirPath() const
 }
 
 void MultiDiskAdaptor::mkdir() const
-  throw(DlAbortEx*)
 {
   for(FileEntries::const_iterator itr = fileEntries.begin();
       itr != fileEntries.end(); itr++) {
@@ -69,7 +69,6 @@ void MultiDiskAdaptor::mkdir() const
 }
 
 void MultiDiskAdaptor::openFile()
-  throw(DlAbortEx*)
 {
   mkdir();
   resetDiskWriterEntries();
@@ -80,7 +79,6 @@ void MultiDiskAdaptor::openFile()
 }
 
 void MultiDiskAdaptor::initAndOpenFile()
-  throw(DlAbortEx*)
 {
   mkdir();
   resetDiskWriterEntries();
@@ -91,7 +89,6 @@ void MultiDiskAdaptor::initAndOpenFile()
 }
 
 void MultiDiskAdaptor::openExistingFile()
-  throw(DlAbortEx*)
 {
   resetDiskWriterEntries();
   for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
@@ -109,7 +106,6 @@ void MultiDiskAdaptor::closeFile()
 }
 
 void MultiDiskAdaptor::onDownloadComplete()
-  throw(DlAbortEx*)
 {
   closeFile();
   openFile();
@@ -117,7 +113,6 @@ void MultiDiskAdaptor::onDownloadComplete()
 
 void MultiDiskAdaptor::writeData(const unsigned char* data, int32_t len,
 				 int64_t offset)
-  throw(DlAbortEx*)
 {
   int64_t fileOffset = offset;
   bool writing = false;
@@ -160,7 +155,6 @@ int32_t MultiDiskAdaptor::calculateLength(const DiskWriterEntryHandle entry,
 }
 
 int32_t MultiDiskAdaptor::readData(unsigned char* data, int32_t len, int64_t offset)
-  throw(DlAbortEx*)
 {
   int64_t fileOffset = offset;
   bool reading = false;
@@ -200,7 +194,6 @@ bool MultiDiskAdaptor::fileExists()
 
 // TODO call DiskWriter::openFile() before calling this function.
 int64_t MultiDiskAdaptor::size() const
-  throw(DlAbortEx*)
 {
   int64_t size = 0;
   for(DiskWriterEntries::const_iterator itr = diskWriterEntries.begin();

+ 8 - 13
src/MultiDiskAdaptor.h

@@ -39,7 +39,6 @@
 #include "Option.h"
 #include "DiskWriter.h"
 #include "File.h"
-#include "DlAbortEx.h"
 
 class DiskWriterEntry {
 private:
@@ -58,19 +57,16 @@ public:
   }
 
   void initAndOpenFile(const string& topDir)
-    throw(DlAbortEx*)
   {
     diskWriter->initAndOpenFile(getFilePath(topDir), fileEntry->getLength());
   }
 
   void openFile(const string& topDir)
-    throw(DlAbortEx*)
   {
     diskWriter->openFile(getFilePath(topDir), fileEntry->getLength());
   }
 
   void openExistingFile(const string& topDir)
-    throw(DlAbortEx*)
   {
     diskWriter->openExistingFile(getFilePath(topDir), fileEntry->getLength());
   }
@@ -86,7 +82,6 @@ public:
   }
 
   int64_t size() const
-    throw(DlAbortEx*)
   {
     return diskWriter->size();
   }
@@ -117,7 +112,7 @@ private:
 
   void resetDiskWriterEntries();
 
-  void mkdir() const throw(DlAbortEx*);
+  void mkdir() const;
 
   bool isInRange(const DiskWriterEntryHandle entry, int64_t offset) const;
 
@@ -133,20 +128,20 @@ public:
 
   virtual ~MultiDiskAdaptor() {}
 
-  virtual void initAndOpenFile() throw(DlAbortEx*);
+  virtual void initAndOpenFile();
 
-  virtual void openFile() throw(DlAbortEx*);
+  virtual void openFile();
 
-  virtual void openExistingFile() throw(DlAbortEx*);
+  virtual void openExistingFile();
 
   virtual void closeFile();
 
-  virtual void onDownloadComplete() throw(DlAbortEx*);
+  virtual void onDownloadComplete();
 
   virtual void writeData(const unsigned char* data, int32_t len,
-			 int64_t offset) throw(DlAbortEx*);
+			 int64_t offset);
 
-  virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) throw(DlAbortEx*);
+  virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset);
 
   virtual bool fileExists();
 
@@ -155,7 +150,7 @@ public:
     return getTopDirPath();
   }
 
-  virtual int64_t size() const throw(DlAbortEx*);
+  virtual int64_t size() const;
 
   virtual FileAllocationIteratorHandle fileAllocationIterator();
 

+ 0 - 1
src/RealtimeCommand.cc

@@ -41,7 +41,6 @@ bool RealtimeCommand::execute()
   try {
     return executeInternal();
   } catch(Exception* e) {
-    //_requestGroup->getSegmentMan()->errors++;
     bool r =  handleException(e);
     delete e;
     return r;

+ 154 - 18
src/RequestGroup.cc

@@ -49,6 +49,12 @@
 #include "DiskAdaptor.h"
 #include "DiskWriterFactory.h"
 #include "RecoverableException.h"
+#include "StreamCheckIntegrityEntry.h"
+#include "CheckIntegrityCommand.h"
+#include "UnknownLengthPieceStorage.h"
+#include "SingleFileDownloadContext.h"
+#include "DlAbortEx.h"
+#include "DownloadFailureException.h"
 #ifdef ENABLE_MESSAGE_DIGEST
 # include "CheckIntegrityCommand.h"
 #endif // ENABLE_MESSAGE_DIGEST
@@ -149,10 +155,7 @@ Commands RequestGroup::createInitialCommand(DownloadEngine* e)
 	_logger->debug("Clearing http/ftp URIs because the current implementation does not allow integrating multi-file torrent and http/ftp.");
 	_uris.clear();
       }
-
-      _pieceStorage = new DefaultPieceStorage(btContext, _option);
-      _pieceStorage->initStorage();
-      initSegmentMan();
+      initPieceStorage();
 
       BtProgressInfoFileHandle progressInfoFile =
 	new DefaultBtProgressInfoFile(_downloadContext,
@@ -201,26 +204,159 @@ Commands RequestGroup::createInitialCommand(DownloadEngine* e)
 	}
       }
       _progressInfoFile = progressInfoFile;
-      Commands commands;
       CheckIntegrityEntryHandle entry =	new BtCheckIntegrityEntry(this);
+      
+      return processCheckIntegrityEntry(entry, e);
+    }
+  }
+#endif // ENABLE_BITTORRENT
+  // TODO I assume here when totallength is set to DownloadContext and it is
+  // not 0, then filepath is also set DownloadContext correctly....
+  if(_downloadContext->getTotalLength() == 0) {
+    return createNextCommand(e, 1);
+  }else {
+    initPieceStorage();
+    BtProgressInfoFileHandle infoFile =
+      new DefaultBtProgressInfoFile(_downloadContext, _pieceStorage, _option);
+    if(!infoFile->exists() && downloadFinishedByFileLength()) {
+      return Commands();
+    }
+    loadAndOpenFile(infoFile);
+    return processCheckIntegrityEntry(new StreamCheckIntegrityEntry(0, this), e);
+  }
+}
+
+Commands RequestGroup::processCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry, DownloadEngine* e)
+{
 #ifdef ENABLE_MESSAGE_DIGEST
-      if(File(getFilePath()).size() > 0 &&
-	 e->option->get(PREF_CHECK_INTEGRITY) == V_TRUE &&
-	 entry->isValidationReady()) {
-	entry->initValidator();
-	CheckIntegrityCommand* command =
-	  new CheckIntegrityCommand(CUIDCounterSingletonHolder::instance()->newID(), this, e, entry);
-	commands.push_back(command);
-      } else
+  if(File(getFilePath()).size() > 0 &&
+     e->option->get(PREF_CHECK_INTEGRITY) == V_TRUE &&
+     entry->isValidationReady()) {
+    entry->initValidator();
+    CheckIntegrityCommand* command =
+      new CheckIntegrityCommand(CUIDCounterSingletonHolder::instance()->newID(), this, e, entry);
+    Commands commands;
+    commands.push_back(command);
+    return commands;
+  } else
 #endif // ENABLE_MESSAGE_DIGEST
-	{
-	  commands = entry->onDownloadIncomplete(e);
+    {
+      return entry->onDownloadIncomplete(e);
+    }
+}
+
+void RequestGroup::initPieceStorage()
+{
+  if(_downloadContext->getTotalLength() == 0) {
+    UnknownLengthPieceStorageHandle ps = new UnknownLengthPieceStorage(_downloadContext, _option);
+    if(!_diskWriterFactory.isNull()) {
+      ps->setDiskWriterFactory(_diskWriterFactory);
+    }
+    _pieceStorage = ps;
+  } else {
+    DefaultPieceStorageHandle ps = new DefaultPieceStorage(_downloadContext, _option);
+    if(!_diskWriterFactory.isNull()) {
+      ps->setDiskWriterFactory(_diskWriterFactory);
+    }
+    _pieceStorage = ps;
+  }
+  _pieceStorage->initStorage();
+  initSegmentMan();
+}
+
+bool RequestGroup::downloadFinishedByFileLength()
+{
+  if(_option->get(PREF_CHECK_INTEGRITY) == V_TRUE &&
+     !_downloadContext->getPieceHashes().empty()) {
+    return false;
+  }
+  // TODO consider the case when the getFilePath() returns dir path. 
+  File outfile(getFilePath());
+  if(outfile.exists() && getTotalLength() == outfile.size()) {
+    _pieceStorage->markAllPiecesDone();
+    _logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, _gid, getFilePath().c_str());
+    return true;
+  } else {
+    return false;
+  }
+}
+
+void RequestGroup::loadAndOpenFile(const BtProgressInfoFileHandle& progressInfoFile)
+{
+  try {
+    if(!isPreLocalFileCheckEnabled()) {
+      _pieceStorage->getDiskAdaptor()->initAndOpenFile();
+      return;
+    }
+    if(progressInfoFile->exists()) {
+      progressInfoFile->load();
+      _pieceStorage->getDiskAdaptor()->openExistingFile();
+    } else {
+      File outfile(getFilePath());    
+      if(outfile.exists() && _option->get(PREF_CONTINUE) == V_TRUE) {
+	if(getTotalLength() < outfile.size()) {
+	  throw new DlAbortEx(EX_FILE_LENGTH_MISMATCH_BETWEEN_LOCAL_AND_REMOTE,
+			      getFilePath().c_str(),
+			      Util::llitos(outfile.size()).c_str(),
+			      Util::llitos(getTotalLength()).c_str());
+	}
+	_pieceStorage->getDiskAdaptor()->openExistingFile();
+	_pieceStorage->markPiecesDone(outfile.size());
+      } else {
+#ifdef ENABLE_MESSAGE_DIGEST
+	if(outfile.exists() && _option->get(PREF_CHECK_INTEGRITY) == V_TRUE) {
+	  _pieceStorage->getDiskAdaptor()->openExistingFile();
+	} else {
+	  shouldCancelDownloadForSafety();
+	  _pieceStorage->getDiskAdaptor()->initAndOpenFile();
 	}
-      return commands;
+#else // ENABLE_MESSAGE_DIGEST
+	shouldCancelDownloadForSafety();
+	_pieceStorage->getDiskAdaptor()->initAndOpenFile();
+#endif // ENABLE_MESSAGE_DIGEST
+      }
     }
+    setProgressInfoFile(progressInfoFile);
+  } catch(RecoverableException* e) {
+    throw new DownloadFailureException(e, EX_DOWNLOAD_ABORTED);
   }
-#endif // ENABLE_BITTORRENT
-  return createNextCommand(e, 1);
+}
+
+void RequestGroup::shouldCancelDownloadForSafety()
+{
+  File outfile(getFilePath());
+  if(outfile.exists() && !_progressInfoFile->exists()) {
+    if(_option->get(PREF_AUTO_FILE_RENAMING) == V_TRUE) {
+      if(tryAutoFileRenaming()) {
+	_logger->notice("File already exists. Renamed to %s.",
+		       getFilePath().c_str());
+      } else {
+	_logger->notice("File renaming failed: %s", getFilePath().c_str());
+	throw new DownloadFailureException(EX_DOWNLOAD_ABORTED);
+      }
+    } else if(_option->get(PREF_ALLOW_OVERWRITE) != V_TRUE) {
+      _logger->notice(MSG_FILE_ALREADY_EXISTS,
+		     getFilePath().c_str(),
+		     _progressInfoFile->getFilename().c_str());
+      throw new DownloadFailureException(EX_DOWNLOAD_ABORTED);
+    }
+  }
+}
+
+bool RequestGroup::tryAutoFileRenaming()
+{
+  string filepath = getFilePath();
+  if(filepath.empty()) {
+    return false;
+  }
+  for(int32_t i = 1; i < 10000; ++i) {
+    File newfile(filepath+"."+Util::itos(i));
+    if(!newfile.exists()) {
+      SingleFileDownloadContextHandle(_downloadContext)->setUFilename(newfile.getBasename());
+      return true;
+    }
+  }
+  return false;
 }
 
 Commands RequestGroup::createNextCommandWithAdj(DownloadEngine* e, int32_t numAdj)

+ 16 - 1
src/RequestGroup.h

@@ -61,10 +61,12 @@ class DiskWriterFactory;
 extern typedef SharedHandle<DiskWriterFactory> DiskWriterFactoryHandle;
 class Option;
 class Logger;
-
 class RequestGroup;
 extern typedef SharedHandle<RequestGroup> RequestGroupHandle;
 extern typedef deque<RequestGroupHandle> RequestGroups;
+class CheckIntegrityEntry;
+extern typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
+
 
 class RequestGroup {
 private:
@@ -124,6 +126,9 @@ private:
 			   int64_t actualTotalLength) const;
 
   void initializePostDownloadHandler();
+
+  bool tryAutoFileRenaming();
+
 public:
   RequestGroup(const Option* option, const Strings& uris);
 
@@ -300,6 +305,16 @@ public:
   void addPostDownloadHandler(const PostDownloadHandlerHandle& handler);
 
   void clearPostDowloadHandler();
+
+  Commands processCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry, DownloadEngine* e);
+
+  void initPieceStorage();
+
+  bool downloadFinishedByFileLength();
+
+  void loadAndOpenFile(const BtProgressInfoFileHandle& progressInfoFile);
+
+  void shouldCancelDownloadForSafety();
 };
 
 typedef SharedHandle<RequestGroup> RequestGroupHandle;

+ 6 - 6
src/RequestGroupMan.cc

@@ -34,7 +34,7 @@
 /* copyright --> */
 #include "RequestGroupMan.h"
 #include "BtProgressInfoFile.h"
-#include "DlAbortEx.h"
+#include "RecoverableException.h"
 #include "RequestGroup.h"
 #include "LogFactory.h"
 #include "DownloadEngine.h"
@@ -120,7 +120,7 @@ void RequestGroupMan::removeStoppedGroup()
       } else {
 	try {
 	  (*itr)->getProgressInfoFile()->save();
-	} catch(DlAbortEx* ex) {
+	} catch(RecoverableException* ex) {
 	  _logger->error(EX_EXCEPTION_CAUGHT, ex);
 	  delete ex;
 	}
@@ -154,7 +154,7 @@ void RequestGroupMan::fillRequestGroupFromReserver(DownloadEngine* e)
       Commands commands = groupToAdd->createInitialCommand(e);
       ++count;
       e->addCommand(commands);
-    } catch(DlAbortEx* ex) {
+    } catch(RecoverableException* ex) {
       _logger->error(EX_EXCEPTION_CAUGHT, ex);
       delete ex;
     }
@@ -175,7 +175,7 @@ Commands RequestGroupMan::getInitialCommands(DownloadEngine* e)
 	Commands nextCommands = (*itr)->createInitialCommand(e);
 	copy(nextCommands.begin(), nextCommands.end(), back_inserter(commands));
 	++itr;
-      } catch(DlAbortEx* e) {
+      } catch(RecoverableException* e) {
 	_logger->error(EX_EXCEPTION_CAUGHT, e);
 	delete e;
       }
@@ -196,7 +196,7 @@ void RequestGroupMan::save()
     } else {
       try {
 	(*itr)->getProgressInfoFile()->save();
-      } catch(DlAbortEx* e) {
+      } catch(RecoverableException* e) {
 	_logger->error(EX_EXCEPTION_CAUGHT, e);
 	delete e;
       }
@@ -220,7 +220,7 @@ void RequestGroupMan::showDownloadResults(ostream& o) const
   o << "\n"
     <<_("Download Results:") << "\n"
     << " (OK):download completed.(ERR):error occurred.(INPR):download in-progress." << "\n"
-    << "idx|stat|path/URI" << "\n"
+    << "gid|stat|path/URI" << "\n"
     << "===+====+======================================================================" << "\n";
   for(RequestGroups::const_iterator itr = _spentGroups.begin();
       itr != _spentGroups.end(); ++itr) {

+ 3 - 16
src/SocketCore.cc

@@ -36,6 +36,8 @@
 #include "message.h"
 #include "a2netcompat.h"
 #include "a2time.h"
+#include "DlRetryEx.h"
+#include "DlAbortEx.h"
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
@@ -81,7 +83,6 @@ SocketCore::~SocketCore() {
 }
 
 void SocketCore::beginListen(int32_t port)
-  throw(DlAbortEx*)
 {
   closeConnection();
   //sockfd = socket(AF_UNSPEC, SOCK_STREAM, PF_UNSPEC);
@@ -118,7 +119,6 @@ void SocketCore::beginListen(int32_t port)
 }
 
 SocketCore* SocketCore::acceptConnection() const
-  throw(DlAbortEx*)
 {
   struct sockaddr_in sockaddr;
   socklen_t len = sizeof(sockaddr);
@@ -133,7 +133,6 @@ SocketCore* SocketCore::acceptConnection() const
 }
 
 void SocketCore::getAddrInfo(pair<string, int32_t>& addrinfo) const
-  throw(DlAbortEx*)
 {
   struct sockaddr_in listenaddr;
   memset((char*)&listenaddr, 0, sizeof(listenaddr));
@@ -146,7 +145,6 @@ void SocketCore::getAddrInfo(pair<string, int32_t>& addrinfo) const
 }
 
 void SocketCore::getPeerInfo(pair<string, int32_t>& peerinfo) const
-  throw(DlAbortEx*)
 {
   struct sockaddr_in peerin;
   memset(&peerin, 0, sizeof(peerin));
@@ -159,7 +157,6 @@ void SocketCore::getPeerInfo(pair<string, int32_t>& peerinfo) const
 }
 
 void SocketCore::establishConnection(const string& host, int32_t port)
-  throw(DlAbortEx*)
 {
   closeConnection();
   sockfd = socket(AF_INET, SOCK_STREAM, 0);
@@ -209,7 +206,6 @@ WSAEWOULDBLOCK
 }
 
 void SocketCore::setNonBlockingMode()
-  throw(DlAbortEx*)
 {
 #ifdef __MINGW32__
   static u_long flag = 1;
@@ -225,7 +221,6 @@ void SocketCore::setNonBlockingMode()
 }
 
 void SocketCore::setBlockingMode()
-  throw(DlAbortEx*)
 {
 #ifdef __MINGW32__
   static u_long flag = 0;
@@ -277,7 +272,6 @@ void SocketCore::closeConnection()
 }
 
 bool SocketCore::isWritable(int32_t timeout) const
-  throw(DlRetryEx*)
 {
   fd_set fds;
   FD_ZERO(&fds);
@@ -303,7 +297,6 @@ bool SocketCore::isWritable(int32_t timeout) const
 }
 
 bool SocketCore::isReadable(int32_t timeout) const
-  throw(DlRetryEx*)
 {
 #ifdef HAVE_LIBGNUTLS
   if(secure && peekBufLength > 0) {
@@ -334,7 +327,6 @@ bool SocketCore::isReadable(int32_t timeout) const
 }
 
 void SocketCore::writeData(const char* data, int32_t len)
-  throw(DlRetryEx*)
 {
   int32_t ret = 0;
 
@@ -351,7 +343,7 @@ void SocketCore::writeData(const char* data, int32_t len)
     }
 #endif // HAVE_LIBSSL
 #ifdef HAVE_LIBGNUTLS
-    if((ret = gnutls_record_send(sslSession, data, len)) == len) {
+    if((ret = gnutls_record_send(sslSession, data, len)) != len) {
       throw new DlRetryEx(EX_SOCKET_SEND, gnutls_strerror(ret));
     }
 #endif // HAVE_LIBGNUTLS
@@ -359,7 +351,6 @@ void SocketCore::writeData(const char* data, int32_t len)
 }
 
 void SocketCore::readData(char* data, int32_t& len)
-  throw(DlRetryEx*)
 {
   int32_t ret = 0;
 
@@ -386,7 +377,6 @@ void SocketCore::readData(char* data, int32_t& len)
 }
 
 void SocketCore::peekData(char* data, int32_t& len)
-  throw(DlRetryEx*)
 {
   int32_t ret = 0;
 
@@ -446,7 +436,6 @@ void SocketCore::addPeekData(char* data, int32_t len)
 }
 
 int32_t SocketCore::gnutlsRecv(char* data, int32_t len)
-  throw(DlRetryEx*)
 {
   int32_t plen = shiftPeekData(data, len);
   if(plen < len) {
@@ -461,7 +450,6 @@ int32_t SocketCore::gnutlsRecv(char* data, int32_t len)
 }
 
 int32_t SocketCore::gnutlsPeek(char* data, int32_t len)
-  throw(DlRetryEx*)
 {
   if(peekBufLength >= len) {
     memcpy(data, peekBuf, len);
@@ -479,7 +467,6 @@ int32_t SocketCore::gnutlsPeek(char* data, int32_t len)
 #endif // HAVE_LIBGNUTLS
 
 void SocketCore::initiateSecureConnection()
-  throw(DlAbortEx*)
 {
 #ifdef HAVE_LIBSSL
   // for SSL

+ 16 - 18
src/SocketCore.h

@@ -36,8 +36,6 @@
 #define _D_SOCKET_CORE_H_
 
 #include "common.h"
-#include "DlRetryEx.h"
-#include "DlAbortEx.h"
 #include <string>
 #include <utility>
 
@@ -77,8 +75,8 @@ private:
 
   int32_t shiftPeekData(char* data, int32_t len);
   void addPeekData(char* data, int32_t len);
-  int32_t gnutlsRecv(char* data, int32_t len) throw(DlRetryEx*);
-  int32_t gnutlsPeek(char* data, int32_t len) throw(DlRetryEx*);
+  int32_t gnutlsRecv(char* data, int32_t len);
+  int32_t gnutlsPeek(char* data, int32_t len);
 #endif // HAVE_LIBGNUTLS
 
   void init();
@@ -99,26 +97,26 @@ public:
    * @param port port to listen. If 0 is specified, os automaticaly
    * choose avaiable port.
    */
-  void beginListen(int32_t port = 0) throw(DlAbortEx*);
+  void beginListen(int32_t port = 0);
 
   /**
    * Stores host address and port of this socket to addrinfo.
    * @param addrinfo placeholder to store host address and port.
    */
-  void getAddrInfo(pair<string, int32_t>& addrinfo) const throw(DlAbortEx*);
+  void getAddrInfo(pair<string, int32_t>& addrinfo) const;
   
   /**
    * Stores peer's address and port to peerinfo.
    * @param peerinfo placeholder to store peer's address and port.
    */
-  void getPeerInfo(pair<string, int32_t>& peerinfo) const throw(DlAbortEx*);
+  void getPeerInfo(pair<string, int32_t>& peerinfo) const;
 
   /**
    * Accepts incoming connection on this socket.
    * You must call beginListen() before calling this method.
    * @return accepted socket. The caller must delete it after using it.
    */
-  SocketCore* acceptConnection() const throw(DlAbortEx*);
+  SocketCore* acceptConnection() const;
 
   /**
    * Connects to the server named host and the destination port is port.
@@ -128,14 +126,14 @@ public:
    * @param host hostname or ip address to connect to
    * @param port service port number to connect to
    */
-  void establishConnection(const string& host, int32_t port) throw(DlAbortEx*);
+  void establishConnection(const string& host, int32_t port);
 
-  void setNonBlockingMode() throw(DlAbortEx*);
+  void setNonBlockingMode();
 
   /**
    * Makes this socket blocking mode.
    */
-  void setBlockingMode() throw(DlAbortEx*);
+  void setBlockingMode();
 
   /**
    * Closes the connection of this socket.
@@ -149,7 +147,7 @@ public:
    * @return true if the socket is available for writing,
    * otherwise returns false.
    */
-  bool isWritable(int32_t timeout) const throw(DlRetryEx*);
+  bool isWritable(int32_t timeout) const;
 
   /**
    * Checks whether this socket is available for reading.
@@ -158,7 +156,7 @@ public:
    * @return true if the socket is available for reading,
    * otherwise returns false.
    */
-  bool isReadable(int32_t timeout) const throw(DlRetryEx*);
+  bool isReadable(int32_t timeout) const;
 
   /**
    * Writes characters into this socket. data is a pointer pointing the first
@@ -168,8 +166,8 @@ public:
    * @param data data to write
    * @param len length of data
    */
-  void writeData(const char* data, int32_t len) throw(DlRetryEx*);
-  void writeData(const string& msg) throw(DlRetryEx*)
+  void writeData(const char* data, int32_t len);
+  void writeData(const string& msg)
   {
     writeData(msg.c_str(), msg.size());
   }
@@ -186,7 +184,7 @@ public:
    * @param len the maximum size data can store. This method assigns
    * the number of bytes read to len.
    */
-  void readData(char* data, int32_t& len) throw(DlRetryEx*);
+  void readData(char* data, int32_t& len);
 
   /**
    * Reads up to len bytes from this socket, but bytes are not removed from
@@ -197,14 +195,14 @@ public:
    * @param len the maximum size data can store. This method assigns
    * the number of bytes read to len.
    */
-  void peekData(char* data, int32_t& len) throw(DlRetryEx*);
+  void peekData(char* data, int32_t& len);
   
   /**
    * Makes this socket secure.
    * If the system has not OpenSSL, then this method do nothing.
    * connection must be established  before calling this method.
    */
-  void initiateSecureConnection() throw(DlAbortEx*);
+  void initiateSecureConnection();
 
   bool operator==(const SocketCore& s) {
     return sockfd == s.sockfd;

+ 4 - 13
src/StreamCheckIntegrityEntry.cc

@@ -54,22 +54,13 @@ StreamCheckIntegrityEntry::~StreamCheckIntegrityEntry() {}
 Commands StreamCheckIntegrityEntry::onDownloadIncomplete(DownloadEngine* e)
 {
   Commands commands;
+  FileAllocationEntryHandle entry =
+    new StreamFileAllocationEntry(_currentRequest, _requestGroup,
+				  popNextCommand());
   if(_requestGroup->needsFileAllocation()) {
-    FileAllocationEntryHandle entry =
-      new StreamFileAllocationEntry(_currentRequest, _requestGroup,
-				    popNextCommand());
     e->_fileAllocationMan->pushFileAllocationEntry(entry);
   } else {
-    if(_nextCommand) {
-      commands.push_back(popNextCommand());
-    } else {
-      Commands streamCommands = _requestGroup->createNextCommandWithAdj(e, -1);
-      Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(),
-											   _currentRequest, _requestGroup, e);
-      
-      commands.push_front(command);
-      copy(streamCommands.begin(), streamCommands.end(), back_inserter(commands));
-    }
+    commands = entry->prepareForNextAction(e);
   }
   return commands;
 }

+ 10 - 6
src/StreamFileAllocationEntry.cc

@@ -58,12 +58,16 @@ Commands StreamFileAllocationEntry::prepareForNextAction(DownloadEngine* e)
      _nextCommand) {
     commands.push_back(popNextCommand());
   } else {
-    Commands streamCommands = _requestGroup->createNextCommandWithAdj(e, -1);
-    Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(),
-											 _currentRequest, _requestGroup, e);
-    
-    commands.push_back(command);
-    copy(streamCommands.begin(), streamCommands.end(), back_inserter(commands));
+    if(_currentRequest.isNull()) {
+      commands = _requestGroup->createNextCommandWithAdj(e, 0);
+    } else {
+      Commands streamCommands = _requestGroup->createNextCommandWithAdj(e, -1);
+      Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(),
+											   _currentRequest, _requestGroup, e);
+      
+      commands.push_back(command);
+      copy(streamCommands.begin(), streamCommands.end(), back_inserter(commands));
+    }
   }
   return commands;
 }

+ 3 - 0
src/TrackerWatcherCommand.cc

@@ -45,6 +45,8 @@
 #include "DiskAdaptor.h"
 #include "RequestGroup.h"
 #include "Option.h"
+#include "DlRetryEx.h"
+#include "DlAbortEx.h"
 
 TrackerWatcherCommand::TrackerWatcherCommand(int32_t cuid,
 					     RequestGroup* requestGroup,
@@ -87,6 +89,7 @@ bool TrackerWatcherCommand::execute() {
       btAnnounce->announceFailure();
       btAnnounce->resetAnnounce();
     } catch(DlRetryEx* ex) {
+      // TODO Can I remove this catch clause?
       logger->error(EX_EXCEPTION_CAUGHT, ex);      
       delete ex;
       btAnnounce->announceFailure();

+ 1 - 1
src/Util.cc

@@ -38,6 +38,7 @@
 #include "Randomizer.h"
 #include "a2netcompat.h"
 #include "a2time.h"
+#include "DlAbortEx.h"
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -331,7 +332,6 @@ void Util::fileCopy(const string& dest, const string& src) {
 }
 
 void Util::rangedFileCopy(const string& dest, const string& src, int64_t srcOffset, int64_t length)
-  throw(DlAbortEx*)
 {
   int32_t bufSize = 4096;
   char buf[bufSize];

+ 1 - 2
src/Util.h

@@ -36,7 +36,6 @@
 #define _D_UTIL_H_
 
 #include "common.h"
-#include "DlAbortEx.h"
 #include "a2time.h"
 #include "FileEntry.h"
 #include <utility>
@@ -100,7 +99,7 @@ public:
 
   static void fileCopy(const string& destFile, const string& src);
 
-  static void rangedFileCopy(const string& destFile, const string& src, int64_t srcOffset, int64_t length) throw(DlAbortEx*);
+  static void rangedFileCopy(const string& destFile, const string& src, int64_t srcOffset, int64_t length);
 
   static bool isPowerOf(int32_t num, int32_t base);
 

+ 1 - 1
src/message.h

@@ -57,7 +57,7 @@
 #define MSG_GOT_NEW_PIECE _("CUID#%d - we got new piece. index=%d")
 #define MSG_GOT_WRONG_PIECE _("CUID#%d - we got wrong piece. index=%d")
 #define MSG_DOWNLOAD_NOT_COMPLETE _("CUID#%d - Download not complete: %s")
-#define MSG_DOWNLOAD_ALREADY_COMPLETED _("CUID#%d - Download has already completed: %s")
+#define MSG_DOWNLOAD_ALREADY_COMPLETED _("#%d - Download has already completed: %s")
 #define MSG_GOOD_CHECKSUM _("CUID#%d - Good checksum: %s")
 #define MSG_BAD_CHECKSUM _("CUID#%d - Bad checksum: %s")
 #define MSG_RESOLVING_HOSTNAME _("CUID#%d - Resolving hostname %s")

+ 1 - 0
src/option_processing.cc

@@ -39,6 +39,7 @@
 #include "OptionHandlerFactory.h"
 #include "Util.h"
 #include "message.h"
+#include "Exception.h"
 #include <fstream>
 #include <sstream>
 

+ 1 - 0
test/UtilTest.cc

@@ -1,5 +1,6 @@
 #include "Util.h"
 #include "FixedNumberRandomizer.h"
+#include "DlAbortEx.h"
 #include <string>
 #include <cppunit/extensions/HelperMacros.h>