summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AbstractCommand.cc200
-rw-r--r--src/AbstractCommand.h32
-rw-r--r--src/AbstractDiskWriter.cc53
-rw-r--r--src/AbstractDiskWriter.h34
-rw-r--r--src/AbstractProxyRequestCommand.cc3
-rw-r--r--src/AbstractProxyRequestCommand.h4
-rw-r--r--src/AbstractProxyResponseCommand.cc5
-rw-r--r--src/AbstractProxyResponseCommand.h4
-rw-r--r--src/AbstractSingleDiskAdaptor.cc29
-rw-r--r--src/AbstractSingleDiskAdaptor.h24
-rw-r--r--src/ActivePeerConnectionCommand.cc18
-rw-r--r--src/ActivePeerConnectionCommand.h24
-rw-r--r--src/AlphaNumberDecorator.h4
-rw-r--r--src/AutoSaveCommand.cc9
-rw-r--r--src/AutoSaveCommand.h5
-rw-r--r--src/BinaryStream.h52
-rw-r--r--src/BtCheckIntegrityEntry.cc (renamed from src/ConsoleDownloadEngine.h)52
-rw-r--r--src/BtCheckIntegrityEntry.h51
-rw-r--r--src/BtContext.h33
-rw-r--r--src/BtContextAwareCommand.cc4
-rw-r--r--src/BtContextAwareCommand.h7
-rw-r--r--src/BtDependency.cc83
-rw-r--r--src/BtDependency.h (renamed from src/TorrentRequestInfo.h)41
-rw-r--r--src/BtFileAllocationEntry.cc (renamed from src/TorrentAutoSaveCommand.cc)35
-rw-r--r--src/BtFileAllocationEntry.h56
-rw-r--r--src/BtPieceMessage.cc4
-rw-r--r--src/BtPostDownloadHandler.cc (renamed from src/ConsoleFileAllocationMonitor.cc)45
-rw-r--r--src/BtPostDownloadHandler.h51
-rw-r--r--src/BtProgressInfoFile.h2
-rw-r--r--src/BtRegistry.cc127
-rw-r--r--src/BtRegistry.h31
-rw-r--r--src/BtRuntime.h10
-rw-r--r--src/BtSetup.cc97
-rw-r--r--src/BtSetup.h (renamed from src/DefaultFileAllocator.h)26
-rw-r--r--src/ByteArrayDiskWriter.cc32
-rw-r--r--src/ByteArrayDiskWriter.h5
-rw-r--r--src/ByteArrayDiskWriterFactory.h52
-rw-r--r--src/CheckIntegrityCommand.cc30
-rw-r--r--src/CheckIntegrityCommand.h7
-rw-r--r--src/CheckIntegrityEntry.cc55
-rw-r--r--src/CheckIntegrityEntry.h32
-rw-r--r--src/CheckIntegrityMan.cc72
-rw-r--r--src/CheckIntegrityMan.h41
-rw-r--r--src/ChecksumCommand.cc12
-rw-r--r--src/ChecksumCommand.h4
-rw-r--r--src/ChunkChecksum.h5
-rw-r--r--src/ChunkChecksumValidator.cc2
-rw-r--r--src/ConsoleDownloadEngine.cc210
-rw-r--r--src/ConsoleStatCalc.cc162
-rw-r--r--src/ConsoleStatCalc.h (renamed from src/TrackerSegmentManFactory.h)24
-rw-r--r--src/CopyDiskAdaptor.cc11
-rw-r--r--src/CopyDiskAdaptor.h5
-rw-r--r--src/DefaultBtContext.cc8
-rw-r--r--src/DefaultBtContext.h20
-rw-r--r--src/DefaultBtProgressInfoFile.cc291
-rw-r--r--src/DefaultBtProgressInfoFile.h54
-rw-r--r--src/DefaultDiskWriter.cc36
-rw-r--r--src/DefaultDiskWriter.h5
-rw-r--r--src/DefaultDiskWriterFactory.h52
-rw-r--r--src/DefaultPeerStorage.cc2
-rw-r--r--src/DefaultPieceStorage.cc240
-rw-r--r--src/DefaultPieceStorage.h41
-rw-r--r--src/DefaultSegmentManFactory.cc11
-rw-r--r--src/DefaultSegmentManFactory.h3
-rw-r--r--src/Dependency.h (renamed from src/FileAllocationMonitor.cc)16
-rw-r--r--src/DirectDiskAdaptor.cc7
-rw-r--r--src/DirectDiskAdaptor.h3
-rw-r--r--src/DiskAdaptor.cc17
-rw-r--r--src/DiskAdaptor.h18
-rw-r--r--src/DiskWriter.h30
-rw-r--r--src/DiskWriterFactory.h (renamed from src/GlowFileAllocator.h)19
-rw-r--r--src/DownloadCommand.cc61
-rw-r--r--src/DownloadCommand.h13
-rw-r--r--src/DownloadContext.h99
-rw-r--r--src/DownloadEngine.cc77
-rw-r--r--src/DownloadEngine.h83
-rw-r--r--src/DownloadEngineFactory.cc203
-rw-r--r--src/DownloadEngineFactory.h31
-rw-r--r--src/File.cc23
-rw-r--r--src/File.h2
-rw-r--r--src/FileAllocationCommand.cc51
-rw-r--r--src/FileAllocationCommand.h11
-rw-r--r--src/FileAllocationDispatcherCommand.cc23
-rw-r--r--src/FileAllocationDispatcherCommand.h11
-rw-r--r--src/FileAllocationEntry.cc39
-rw-r--r--src/FileAllocationEntry.h35
-rw-r--r--src/FileAllocationIterator.h56
-rw-r--r--src/FileAllocationMan.cc (renamed from src/TorrentConsoleDownloadEngine.cc)68
-rw-r--r--src/FileAllocationMan.h52
-rw-r--r--src/FileEntry.cc15
-rw-r--r--src/FileEntry.h14
-rw-r--r--src/FillRequestGroupCommand.cc26
-rw-r--r--src/FillRequestGroupCommand.h17
-rw-r--r--src/FtpConnection.cc66
-rw-r--r--src/FtpConnection.h32
-rw-r--r--src/FtpDownloadCommand.cc1
-rw-r--r--src/FtpInitiateConnectionCommand.cc12
-rw-r--r--src/FtpInitiateConnectionCommand.h5
-rw-r--r--src/FtpNegotiationCommand.cc23
-rw-r--r--src/FtpNegotiationCommand.h3
-rw-r--r--src/GrowSegment.cc54
-rw-r--r--src/GrowSegment.h97
-rw-r--r--src/HaveEraseCommand.cc36
-rw-r--r--src/HaveEraseCommand.h21
-rw-r--r--src/HttpConnection.cc9
-rw-r--r--src/HttpConnection.h8
-rw-r--r--src/HttpDownloadCommand.cc5
-rw-r--r--src/HttpHeaderProcessor.cc6
-rw-r--r--src/HttpHeaderProcessor.h10
-rw-r--r--src/HttpInitiateConnectionCommand.cc11
-rw-r--r--src/HttpInitiateConnectionCommand.h5
-rw-r--r--src/HttpRequest.cc10
-rw-r--r--src/HttpRequest.h2
-rw-r--r--src/HttpRequestCommand.cc4
-rw-r--r--src/HttpResponse.cc3
-rw-r--r--src/HttpResponse.h4
-rw-r--r--src/HttpResponseCommand.cc72
-rw-r--r--src/HttpResponseCommand.h9
-rw-r--r--src/IteratableChecksumValidator.cc2
-rw-r--r--src/IteratableChunkChecksumValidator.cc64
-rw-r--r--src/IteratableChunkChecksumValidator.h48
-rw-r--r--src/Makefile.am63
-rw-r--r--src/Makefile.in305
-rw-r--r--src/MessageDigestHelper.cc13
-rw-r--r--src/MessageDigestHelper.h12
-rw-r--r--src/Metalink2RequestGroup.cc (renamed from src/MetalinkRequestInfo.cc)141
-rw-r--r--src/Metalink2RequestGroup.h (renamed from src/MetalinkRequestInfo.h)32
-rw-r--r--src/MetalinkPostDownloadHandler.cc48
-rw-r--r--src/MetalinkPostDownloadHandler.h51
-rw-r--r--src/MultiDiskAdaptor.cc42
-rw-r--r--src/MultiDiskAdaptor.h26
-rw-r--r--src/MultiDiskWriter.cc214
-rw-r--r--src/MultiDiskWriter.h89
-rw-r--r--src/MultiFileAllocationIterator.cc (renamed from src/GlowFileAllocator.cc)94
-rw-r--r--src/MultiFileAllocationIterator.h (renamed from src/FileAllocationMonitor.h)50
-rw-r--r--src/MultiUrlRequestInfo.cc82
-rw-r--r--src/MultiUrlRequestInfo.h31
-rw-r--r--src/NullProgressInfoFile.h60
-rw-r--r--src/Peer.cc8
-rw-r--r--src/Peer.h2
-rw-r--r--src/PeerAbstractCommand.cc19
-rw-r--r--src/PeerAbstractCommand.h27
-rw-r--r--src/PeerChokeCommand.cc10
-rw-r--r--src/PeerChokeCommand.h16
-rw-r--r--src/PeerConnection.cc21
-rw-r--r--src/PeerConnection.h2
-rw-r--r--src/PeerInitiateConnectionCommand.cc28
-rw-r--r--src/PeerInitiateConnectionCommand.h21
-rw-r--r--src/PeerInteractionCommand.cc31
-rw-r--r--src/PeerInteractionCommand.h15
-rw-r--r--src/PeerListenCommand.cc47
-rw-r--r--src/PeerListenCommand.h16
-rw-r--r--src/PeerReceiveHandshakeCommand.cc101
-rw-r--r--src/PeerReceiveHandshakeCommand.h68
-rw-r--r--src/PeerStorage.h65
-rw-r--r--src/Piece.cc13
-rw-r--r--src/Piece.h5
-rw-r--r--src/PieceStorage.h42
-rw-r--r--src/PiecedSegment.cc (renamed from src/ConsoleFileAllocationMonitor.h)111
-rw-r--r--src/PiecedSegment.h94
-rw-r--r--src/PostDownloadHandler.cc46
-rw-r--r--src/PostDownloadHandler.h (renamed from src/TorrentAutoSaveCommand.h)38
-rw-r--r--src/ProgressAwareEntry.h6
-rw-r--r--src/RealtimeCommand.cc2
-rw-r--r--src/RealtimeCommand.h9
-rw-r--r--src/Request.cc2
-rw-r--r--src/RequestGroup.cc531
-rw-r--r--src/RequestGroup.h315
-rw-r--r--src/RequestGroupAware.cc (renamed from src/TrackerSegmentManFactory.cc)17
-rw-r--r--src/RequestGroupAware.h (renamed from src/TorrentConsoleDownloadEngine.h)19
-rw-r--r--src/RequestGroupEntry.cc24
-rw-r--r--src/RequestGroupEntry.h62
-rw-r--r--src/RequestGroupMan.cc204
-rw-r--r--src/RequestGroupMan.h121
-rw-r--r--src/SeedCheckCommand.cc7
-rw-r--r--src/SeedCheckCommand.h14
-rw-r--r--src/Segment.cc12
-rw-r--r--src/Segment.h49
-rw-r--r--src/SegmentMan.cc438
-rw-r--r--src/SegmentMan.h214
-rw-r--r--src/SegmentManFactory.h3
-rw-r--r--src/SingleFileAllocationIterator.cc67
-rw-r--r--src/SingleFileAllocationIterator.h66
-rw-r--r--src/SingleFileDownloadContext.h165
-rw-r--r--src/SocketCore.cc83
-rw-r--r--src/SocketCore.h37
-rw-r--r--src/StatCalc.h (renamed from src/FileAllocator.h)34
-rw-r--r--src/StreamCheckIntegrityEntry.cc (renamed from src/TorrentDownloadEngine.h)88
-rw-r--r--src/StreamCheckIntegrityEntry.h65
-rw-r--r--src/StreamFileAllocationEntry.cc (renamed from src/DefaultFileAllocator.cc)63
-rw-r--r--src/StreamFileAllocationEntry.h (renamed from src/TrackerUpdateCommand.h)35
-rw-r--r--src/TimeBasedCommand.cc6
-rw-r--r--src/TimeBasedCommand.h8
-rw-r--r--src/TorrentDownloadEngine.cc116
-rw-r--r--src/TorrentRequestInfo.cc130
-rw-r--r--src/TrackerUpdateCommand.cc115
-rw-r--r--src/TrackerWatcherCommand.cc146
-rw-r--r--src/TrackerWatcherCommand.h33
-rw-r--r--src/TransferStat.cc45
-rw-r--r--src/TransferStat.h121
-rw-r--r--src/UnknownLengthPieceStorage.cc171
-rw-r--r--src/UnknownLengthPieceStorage.h272
-rw-r--r--src/Util.cc32
-rw-r--r--src/Util.h3
-rw-r--r--src/main.cc762
-rw-r--r--src/messageDigest.h4
-rw-r--r--src/option_processing.cc434
-rw-r--r--src/version_usage.cc305
208 files changed, 7321 insertions, 4854 deletions
diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc
index 38a49a01..e4bd954b 100644
--- a/src/AbstractCommand.cc
+++ b/src/AbstractCommand.cc
@@ -33,44 +33,64 @@
*/
/* copyright --> */
#include "AbstractCommand.h"
+#include "SegmentMan.h"
+#include "NameResolver.h"
+#include "CUIDCounter.h"
#include "DlAbortEx.h"
#include "DlRetryEx.h"
+#include "FatalException.h"
#include "InitiateConnectionCommandFactory.h"
#include "Util.h"
#include "message.h"
#include "SleepCommand.h"
#include "prefs.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,
const RequestHandle& req,
RequestGroup* requestGroup,
DownloadEngine* e,
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),
- nameResolverCheck(false) {
-
+ nameResolverCheck(false)
+{
setReadCheckSocket(socket);
timeout = this->e->option->getAsInt(PREF_TIMEOUT);
- ++_requestGroup->numConnection;
+ _requestGroup->increaseStreamConnection();
}
AbstractCommand::~AbstractCommand() {
disableReadCheckSocket();
disableWriteCheckSocket();
- --_requestGroup->numConnection;
+ _requestGroup->decreaseStreamConnection();
}
bool AbstractCommand::execute() {
try {
- if(_requestGroup->getSegmentMan()->finished()) {
+ if(_requestGroup->downloadFinished() || _requestGroup->isHaltRequested()) {
//logger->debug("CUID#%d - finished.", cuid);
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) {
logger->info(MSG_ABORT_REQUESTED, cuid);
onAbort(0);
@@ -86,9 +106,8 @@ bool AbstractCommand::execute() {
#endif // ENABLE_ASYNC_DNS
!checkSocketIsReadable && !checkSocketIsWritable && !nameResolverCheck) {
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);
if(segment.isNull()) {
logger->info(MSG_NO_SEGMENT_AVAILABLE, cuid);
@@ -98,26 +117,17 @@ bool AbstractCommand::execute() {
}
return executeInternal();
} else {
-
if(checkPoint.elapsed(timeout)) {
throw new DlRetryEx(EX_TIME_OUT);
}
e->commands.push_back(this);
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) {
logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
onAbort(err);
delete(err);
req->resetUrl();
- _requestGroup->getSegmentMan()->errors++;
tryReserved();
return true;
} catch(DlRetryEx* err) {
@@ -132,13 +142,16 @@ bool AbstractCommand::execute() {
logger->info(MSG_MAX_TRY, cuid, req->getTryCount());
logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
delete(err);
- _requestGroup->getSegmentMan()->errors++;
tryReserved();
return true;
} else {
delete(err);
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) {
- _requestGroup->getSegmentMan()->cancelSegment(cuid);
+ if(!_requestGroup->getPieceStorage().isNull()) {
+ _requestGroup->getSegmentMan()->cancelSegment(cuid);
+ }
Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, req, _requestGroup, e);
if(wait == 0) {
e->commands.push_back(command);
@@ -162,7 +177,9 @@ bool AbstractCommand::prepareForRetry(int32_t wait) {
void AbstractCommand::onAbort(Exception* ex) {
logger->debug(MSG_UNREGISTER_CUID, cuid);
//_segmentMan->unregisterId(cuid);
- _requestGroup->getSegmentMan()->cancelSegment(cuid);
+ if(!_requestGroup->getPieceStorage().isNull()) {
+ _requestGroup->getSegmentMan()->cancelSegment(cuid);
+ }
}
void AbstractCommand::disableReadCheckSocket() {
@@ -272,3 +289,138 @@ bool AbstractCommand::nameResolveFinished() const {
return false;
}
#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));
+ }
+}
diff --git a/src/AbstractCommand.h b/src/AbstractCommand.h
index 89f1d975..26fd4ddb 100644
--- a/src/AbstractCommand.h
+++ b/src/AbstractCommand.h
@@ -36,20 +36,24 @@
#define _D_ABSTRACT_COMMAND_H_
#include "Command.h"
-#include "Request.h"
-#include "DownloadEngine.h"
-#include "SegmentMan.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:
Time checkPoint;
int32_t timeout;
protected:
RequestHandle req;
- RequestGroup* _requestGroup;
DownloadEngine* e;
SocketHandle socket;
SegmentHandle segment;
@@ -70,12 +74,26 @@ protected:
virtual bool nameResolveFinished() const;
#endif // ENABLE_ASYNC_DNS
void setTimeout(int32_t timeout) { this->timeout = timeout; }
+
+ void loadAndOpenFile();
+
+ bool tryAutoFileRenaming();
+
+ void initPieceStorage();
+
+ bool downloadFinishedByFileLength();
+
+ void prepareForNextAction(Command* nextCommand = 0);
+
+ void shouldCancelDownloadForSafety();
+
private:
bool checkSocketIsReadable;
bool checkSocketIsWritable;
SocketHandle readCheckTarget;
SocketHandle writeCheckTarget;
bool nameResolverCheck;
+
public:
AbstractCommand(int32_t cuid, const RequestHandle& req, RequestGroup* requestGroup, DownloadEngine* e, const SocketHandle& s = SocketHandle());
virtual ~AbstractCommand();
diff --git a/src/AbstractDiskWriter.cc b/src/AbstractDiskWriter.cc
index c382fee1..af509244 100644
--- a/src/AbstractDiskWriter.cc
+++ b/src/AbstractDiskWriter.cc
@@ -33,7 +33,6 @@
*/
/* copyright --> */
#include "AbstractDiskWriter.h"
-#include "DlAbortEx.h"
#include "File.h"
#include "Util.h"
#include "message.h"
@@ -47,8 +46,6 @@
AbstractDiskWriter::AbstractDiskWriter():
fd(-1),
- fileAllocator(0),
- glowFileAllocator(0),
logger(LogFactory::getInstance())
{}
@@ -57,7 +54,9 @@ AbstractDiskWriter::~AbstractDiskWriter()
closeFile();
}
-void AbstractDiskWriter::openFile(const string& filename, int64_t totalLength) {
+void AbstractDiskWriter::openFile(const string& filename, int64_t totalLength)
+ throw(DlAbortEx*)
+{
File f(filename);
if(f.exists()) {
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) {
close(fd);
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;
File f(filename);
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) {
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;
// TODO proper filename handling needed
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);
}
-int32_t AbstractDiskWriter::readDataInternal(char* data, int32_t len) {
+int32_t AbstractDiskWriter::readDataInternal(unsigned char* data, int32_t 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)) {
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);
if(writeDataInternal(data, len) < 0) {
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;
seek(offset);
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)
+ throw(DlAbortEx*)
{
+ if(fd == -1) {
+ throw new DlAbortEx("File not opened.");
+ }
ftruncate(fd, 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.");
+ }
struct stat fileStat;
if(fstat(fd, &fileStat) < 0) {
return 0;
diff --git a/src/AbstractDiskWriter.h b/src/AbstractDiskWriter.h
index f6b2d426..e5d8eb14 100644
--- a/src/AbstractDiskWriter.h
+++ b/src/AbstractDiskWriter.h
@@ -36,52 +36,40 @@
#define _D_ABSTRACT_DISK_WRITER_H_
#include "DiskWriter.h"
-#include "FileAllocator.h"
#include "Logger.h"
+#include "DlAbortEx.h"
class AbstractDiskWriter : public DiskWriter {
protected:
string filename;
int32_t fd;
- FileAllocatorHandle fileAllocator;
- FileAllocatorHandle glowFileAllocator;
const Logger* logger;
- void createFile(const string& filename, int32_t addFlags = 0);
+ void createFile(const string& filename, int32_t addFlags = 0) throw(DlAbortEx*);
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:
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 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_
diff --git a/src/AbstractProxyRequestCommand.cc b/src/AbstractProxyRequestCommand.cc
index b0257a89..cd1f4a5a 100644
--- a/src/AbstractProxyRequestCommand.cc
+++ b/src/AbstractProxyRequestCommand.cc
@@ -33,6 +33,9 @@
*/
/* copyright --> */
#include "AbstractProxyRequestCommand.h"
+#include "DownloadEngine.h"
+#include "RequestGroup.h"
+#include "Request.h"
#include "HttpConnection.h"
#include "prefs.h"
diff --git a/src/AbstractProxyRequestCommand.h b/src/AbstractProxyRequestCommand.h
index 184ccd92..18dc1336 100644
--- a/src/AbstractProxyRequestCommand.h
+++ b/src/AbstractProxyRequestCommand.h
@@ -36,7 +36,9 @@
#define _D_ABSTRACT_PROXY_REQUEST_COMMAND_H_
#include "AbstractCommand.h"
-#include "HttpConnection.h"
+
+class HttpConnection;
+extern typedef SharedHandle<HttpConnection> HttpConnectionHandle;
class AbstractProxyRequestCommand : public AbstractCommand {
protected:
diff --git a/src/AbstractProxyResponseCommand.cc b/src/AbstractProxyResponseCommand.cc
index eaf89762..1c25a0ca 100644
--- a/src/AbstractProxyResponseCommand.cc
+++ b/src/AbstractProxyResponseCommand.cc
@@ -33,6 +33,11 @@
*/
/* copyright --> */
#include "AbstractProxyResponseCommand.h"
+#include "HttpConnection.h"
+#include "Request.h"
+#include "RequestGroup.h"
+#include "DownloadEngine.h"
+#include "HttpResponse.h"
#include "HttpRequestCommand.h"
#include "DlRetryEx.h"
#include "message.h"
diff --git a/src/AbstractProxyResponseCommand.h b/src/AbstractProxyResponseCommand.h
index a5770903..44aa8647 100644
--- a/src/AbstractProxyResponseCommand.h
+++ b/src/AbstractProxyResponseCommand.h
@@ -36,7 +36,9 @@
#define _D_ABSTRACT_PROXY_RESPONSE_COMMAND_H_
#include "AbstractCommand.h"
-#include "HttpConnection.h"
+
+class HttpConnection;
+extern typedef SharedHandle<HttpConnection> HttpConnectionHandle;
class AbstractProxyResponseCommand : public AbstractCommand {
protected:
diff --git a/src/AbstractSingleDiskAdaptor.cc b/src/AbstractSingleDiskAdaptor.cc
index e0bec6ee..44e2e846 100644
--- a/src/AbstractSingleDiskAdaptor.cc
+++ b/src/AbstractSingleDiskAdaptor.cc
@@ -34,28 +34,40 @@
/* copyright --> */
#include "AbstractSingleDiskAdaptor.h"
#include "File.h"
+#include "SingleFileAllocationIterator.h"
-void AbstractSingleDiskAdaptor::initAndOpenFile() {
+void AbstractSingleDiskAdaptor::initAndOpenFile()
+ throw(DlAbortEx*)
+{
diskWriter->initAndOpenFile(getFilePath(), totalLength);
}
-void AbstractSingleDiskAdaptor::openFile() {
+void AbstractSingleDiskAdaptor::openFile()
+ throw(DlAbortEx*)
+{
diskWriter->openFile(getFilePath(), totalLength);
}
-void AbstractSingleDiskAdaptor::closeFile() {
+void AbstractSingleDiskAdaptor::closeFile()
+{
diskWriter->closeFile();
}
-void AbstractSingleDiskAdaptor::openExistingFile() {
+void AbstractSingleDiskAdaptor::openExistingFile()
+ throw(DlAbortEx*)
+{
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);
}
-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);
}
@@ -63,3 +75,8 @@ bool AbstractSingleDiskAdaptor::fileExists()
{
return File(getFilePath()).exists();
}
+
+FileAllocationIteratorHandle AbstractSingleDiskAdaptor::fileAllocationIterator()
+{
+ return new SingleFileAllocationIterator(this);
+}
diff --git a/src/AbstractSingleDiskAdaptor.h b/src/AbstractSingleDiskAdaptor.h
index c4dc7e80..ee0733b8 100644
--- a/src/AbstractSingleDiskAdaptor.h
+++ b/src/AbstractSingleDiskAdaptor.h
@@ -37,6 +37,7 @@
#include "DiskAdaptor.h"
#include "DiskWriter.h"
+#include "DlAbortEx.h"
class AbstractSingleDiskAdaptor : public DiskAdaptor {
protected:
@@ -47,26 +48,33 @@ public:
virtual ~AbstractSingleDiskAdaptor() {}
- virtual void initAndOpenFile();
+ virtual void initAndOpenFile() throw(DlAbortEx*);
- virtual void openFile();
+ virtual void openFile() throw(DlAbortEx*);
virtual void closeFile();
- virtual void openExistingFile();
+ virtual void openExistingFile() throw(DlAbortEx*);
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 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) {
this->diskWriter = diskWriter;
}
diff --git a/src/ActivePeerConnectionCommand.cc b/src/ActivePeerConnectionCommand.cc
index d85b1225..27c0798d 100644
--- a/src/ActivePeerConnectionCommand.cc
+++ b/src/ActivePeerConnectionCommand.cc
@@ -37,6 +37,22 @@
#include "CUIDCounter.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() {
if(btRuntime->isHalt()) {
return true;
@@ -63,7 +79,7 @@ void ActivePeerConnectionCommand::connectToPeer(const PeerHandle& peer)
}
peer->cuid = CUIDCounterSingletonHolder::instance()->newID();
PeerInitiateConnectionCommand* command =
- new PeerInitiateConnectionCommand(peer->cuid, peer, e, btContext);
+ new PeerInitiateConnectionCommand(peer->cuid, _requestGroup, peer, e, btContext);
e->commands.push_back(command);
logger->info(MSG_CONNECTING_TO_PEER,
cuid, peer->ipaddr.c_str());
diff --git a/src/ActivePeerConnectionCommand.h b/src/ActivePeerConnectionCommand.h
index 2bc919f9..4877101e 100644
--- a/src/ActivePeerConnectionCommand.h
+++ b/src/ActivePeerConnectionCommand.h
@@ -35,30 +35,30 @@
#ifndef _D_ACTIVE_PEER_CONNECTION_COMMAND_H_
#define _D_ACTIVE_PEER_CONNECTION_COMMAND_H_
+#include "Command.h"
#include "BtContextAwareCommand.h"
-#include "TorrentDownloadEngine.h"
+#include "DownloadEngine.h"
#include "TimeA2.h"
+#include "RequestGroupAware.h"
-class ActivePeerConnectionCommand : public BtContextAwareCommand {
+class ActivePeerConnectionCommand : public Command,
+ public BtContextAwareCommand,
+ public RequestGroupAware
+{
private:
int32_t interval; // UNIT: sec
- TorrentDownloadEngine* e;
+ DownloadEngine* e;
Time checkPoint;
int32_t _lowestSpeedLimit; // UNIT: byte/sec
int32_t _numNewConnection; // the number of the connection to establish.
public:
ActivePeerConnectionCommand(int cuid,
- TorrentDownloadEngine* e,
+ RequestGroup* requestGroup,
+ DownloadEngine* e,
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();
diff --git a/src/AlphaNumberDecorator.h b/src/AlphaNumberDecorator.h
index 03f9dc7a..db1543f8 100644
--- a/src/AlphaNumberDecorator.h
+++ b/src/AlphaNumberDecorator.h
@@ -36,7 +36,7 @@
#define _D_ALPHA_NUMBER_DECORATOR_H_
#include "NumberDecorator.h"
-#include "FatalException.h"
+#include "DlAbortEx.h"
class AlphaNumberDecorator : public NumberDecorator
{
@@ -64,7 +64,7 @@ public:
virtual string decorate(int32_t number)
{
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) {
return widen(_zero, _width);
diff --git a/src/AutoSaveCommand.cc b/src/AutoSaveCommand.cc
index a894ac7e..238eb655 100644
--- a/src/AutoSaveCommand.cc
+++ b/src/AutoSaveCommand.cc
@@ -33,10 +33,17 @@
*/
/* copyright --> */
#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()
{
- if(_e->_requestGroupMan->downloadFinished()) {
+ if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
_exit = true;
}
}
diff --git a/src/AutoSaveCommand.h b/src/AutoSaveCommand.h
index 6a1f23ff..e0a700c2 100644
--- a/src/AutoSaveCommand.h
+++ b/src/AutoSaveCommand.h
@@ -40,10 +40,9 @@
class AutoSaveCommand : public TimeBasedCommand
{
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();
diff --git a/src/BinaryStream.h b/src/BinaryStream.h
new file mode 100644
index 00000000..1d11d8e5
--- /dev/null
+++ b/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_
diff --git a/src/ConsoleDownloadEngine.h b/src/BtCheckIntegrityEntry.cc
index a1f61fcd..29558141 100644
--- a/src/ConsoleDownloadEngine.h
+++ b/src/BtCheckIntegrityEntry.cc
@@ -32,37 +32,29 @@
* files in the program, then also delete it here.
*/
/* 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 "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;
+}
diff --git a/src/BtCheckIntegrityEntry.h b/src/BtCheckIntegrityEntry.h
new file mode 100644
index 00000000..1b5e25cd
--- /dev/null
+++ b/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_
diff --git a/src/BtContext.h b/src/BtContext.h
index 69d52029..5d9d493a 100644
--- a/src/BtContext.h
+++ b/src/BtContext.h
@@ -35,57 +35,40 @@
#ifndef _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 MAX_PEER_ERROR 5
#define MAX_PEERS 55
+class AnnounceTier;
+extern typedef SharedHandle<AnnounceTier> AnnounceTierHandle;
typedef deque<AnnounceTierHandle> AnnounceTiers;
-class BtContext {
+class RequestGroup;
+
+class BtContext:public DownloadContext {
public:
virtual ~BtContext() {}
- enum FILE_MODE {
- SINGLE,
- MULTI
- };
-
virtual const unsigned char* getInfoHash() const = 0;
virtual int32_t getInfoHashLength() 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 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
*/
virtual const unsigned char* getPeerId() = 0;
virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize) = 0;
+
+ virtual RequestGroup* getOwnerRequestGroup() = 0;
};
diff --git a/src/BtContextAwareCommand.cc b/src/BtContextAwareCommand.cc
index b45d6ddc..ccc42f0b 100644
--- a/src/BtContextAwareCommand.cc
+++ b/src/BtContextAwareCommand.cc
@@ -35,9 +35,7 @@
#include "BtContextAwareCommand.h"
#include "BtRegistry.h"
-BtContextAwareCommand::BtContextAwareCommand(int cuid,
- const BtContextHandle& btContext):
- Command(cuid),
+BtContextAwareCommand::BtContextAwareCommand(const BtContextHandle& btContext):
btContext(btContext),
btRuntime(BT_RUNTIME(btContext)),
pieceStorage(PIECE_STORAGE(btContext)),
diff --git a/src/BtContextAwareCommand.h b/src/BtContextAwareCommand.h
index 44bbd9b6..3baf2ea7 100644
--- a/src/BtContextAwareCommand.h
+++ b/src/BtContextAwareCommand.h
@@ -35,7 +35,7 @@
#ifndef _D_BT_CONTEXT_AWARE_COMMAND_H_
#define _D_BT_CONTEXT_AWARE_COMMAND_H_
-#include "Command.h"
+#include "common.h"
#include "BtContext.h"
#include "BtRuntime.h"
#include "PieceStorage.h"
@@ -43,7 +43,8 @@
#include "BtAnnounce.h"
#include "BtProgressInfoFile.h"
-class BtContextAwareCommand : public Command {
+class BtContextAwareCommand
+{
protected:
BtContextHandle btContext;
BtRuntimeHandle btRuntime;
@@ -52,7 +53,7 @@ protected:
BtAnnounceHandle btAnnounce;
BtProgressInfoFileHandle btProgressInfoFile;
public:
- BtContextAwareCommand(int cuid, const BtContextHandle& btContext);
+ BtContextAwareCommand(const BtContextHandle& btContext);
virtual ~BtContextAwareCommand();
};
diff --git a/src/BtDependency.cc b/src/BtDependency.cc
new file mode 100644
index 00000000..8be2266e
--- /dev/null
+++ b/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;
+ }
+}
diff --git a/src/TorrentRequestInfo.h b/src/BtDependency.h
index 7b71d89b..b688a957 100644
--- a/src/TorrentRequestInfo.h
+++ b/src/BtDependency.h
@@ -32,30 +32,33 @@
* files in the program, then also delete it here.
*/
/* 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:
- 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_
diff --git a/src/TorrentAutoSaveCommand.cc b/src/BtFileAllocationEntry.cc
index 28f343dd..b3c72525 100644
--- a/src/TorrentAutoSaveCommand.cc
+++ b/src/BtFileAllocationEntry.cc
@@ -32,27 +32,22 @@
* files in the program, then also delete it here.
*/
/* 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;
}
diff --git a/src/BtFileAllocationEntry.h b/src/BtFileAllocationEntry.h
new file mode 100644
index 00000000..9b21f856
--- /dev/null
+++ b/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_
diff --git a/src/BtPieceMessage.cc b/src/BtPieceMessage.cc
index d3587583..a8def5ce 100644
--- a/src/BtPieceMessage.cc
+++ b/src/BtPieceMessage.cc
@@ -39,8 +39,8 @@
#include "DlAbortEx.h"
#include "BtChokingEvent.h"
#include "BtCancelSendingPieceEvent.h"
-#include "DiskAdaptorWriter.h"
#include "MessageDigestHelper.h"
+#include "DiskAdaptor.h"
void BtPieceMessage::setBlock(const unsigned char* block, int32_t blockLength) {
delete [] this->block;
@@ -193,7 +193,7 @@ bool BtPieceMessage::checkPieceHash(const PieceHandle& piece) {
int64_t offset =
((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());
}
diff --git a/src/ConsoleFileAllocationMonitor.cc b/src/BtPostDownloadHandler.cc
index b6245b90..b2fc19b9 100644
--- a/src/ConsoleFileAllocationMonitor.cc
+++ b/src/BtPostDownloadHandler.cc
@@ -32,28 +32,31 @@
* files in the program, then also delete it here.
*/
/* 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;
}
diff --git a/src/BtPostDownloadHandler.h b/src/BtPostDownloadHandler.h
new file mode 100644
index 00000000..f1cb1638
--- /dev/null
+++ b/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_
diff --git a/src/BtProgressInfoFile.h b/src/BtProgressInfoFile.h
index e4d8f2ff..968e5525 100644
--- a/src/BtProgressInfoFile.h
+++ b/src/BtProgressInfoFile.h
@@ -43,8 +43,6 @@ public:
virtual string getFilename() = 0;
- virtual void setFilename(const string& filename) = 0;
-
virtual bool exists() = 0;
virtual void save() = 0;
diff --git a/src/BtRegistry.cc b/src/BtRegistry.cc
index e74b86bf..3358da13 100644
--- a/src/BtRegistry.cc
+++ b/src/BtRegistry.cc
@@ -35,6 +35,7 @@
#include "BtRegistry.h"
#include "DlAbortEx.h"
+BtContextMap BtRegistry::btContextMap;
PeerStorageMap BtRegistry::peerStorageMap;
PieceStorageMap BtRegistry::pieceStorageMap;
BtAnnounceMap BtRegistry::btAnnounceMap;
@@ -42,93 +43,77 @@ BtRuntimeMap BtRegistry::btRuntimeMap;
BtProgressInfoFileMap BtRegistry::btProgressInfoFileMap;
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
-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,
- 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,
- 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,
- 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,
- 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
@@ -150,7 +135,8 @@ BtRegistry::unregisterPeerObjectCluster(const string& key)
peerObjectClusterRegistry.unregisterHandle(key);
}
-void BtRegistry::clear() {
+void BtRegistry::unregisterAll() {
+ btContextMap.clear();
peerStorageMap.clear();
pieceStorageMap.clear();
btAnnounceMap.clear();
@@ -158,3 +144,14 @@ void BtRegistry::clear() {
btProgressInfoFileMap.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);
+}
diff --git a/src/BtRegistry.h b/src/BtRegistry.h
index 7a9eafb0..d0722f05 100644
--- a/src/BtRegistry.h
+++ b/src/BtRegistry.h
@@ -36,6 +36,7 @@
#define _D_BT_REGISTRY_H_
#include "common.h"
+#include "BtContext.h"
#include "PeerStorage.h"
#include "PieceStorage.h"
#include "BtAnnounce.h"
@@ -45,11 +46,12 @@
#include "HandleRegistry.h"
#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
typedef HandleRegistry<string, PeerObject> PeerObjectCluster;
@@ -60,6 +62,7 @@ class BtRegistry {
private:
BtRegistry() {}
+ static BtContextMap btContextMap;
static PeerStorageMap peerStorageMap;
static PieceStorageMap pieceStorageMap;
static BtAnnounceMap btAnnounceMap;
@@ -67,24 +70,28 @@ private:
static BtProgressInfoFileMap btProgressInfoFileMap;
static PeerObjectClusterRegistry peerObjectClusterRegistry;
public:
+ static BtContextHandle getBtContext(const string& key);
+ static void registerBtContext(const string& key,
+ const BtContextHandle& btContext);
+
static PeerStorageHandle getPeerStorage(const string& key);
- static bool registerPeerStorage(const string& key,
+ static void registerPeerStorage(const string& key,
const PeerStorageHandle& peer);
static PieceStorageHandle getPieceStorage(const string& key);
- static bool registerPieceStorage(const string& key,
+ static void registerPieceStorage(const string& key,
const PieceStorageHandle& pieceStorage);
static BtRuntimeHandle getBtRuntime(const string& key);
- static bool registerBtRuntime(const string& key,
+ static void registerBtRuntime(const string& key,
const BtRuntimeHandle& btRuntime);
static BtAnnounceHandle getBtAnnounce(const string& key);
- static bool registerBtAnnounce(const string& key,
+ static void registerBtAnnounce(const string& key,
const BtAnnounceHandle& btAnnounce);
static BtProgressInfoFileHandle getBtProgressInfoFile(const string& key);
- static bool registerBtProgressInfoFile(const string& key,
+ static void registerBtProgressInfoFile(const string& key,
const BtProgressInfoFileHandle& btProgressInfoFile);
// for PeerObject
@@ -98,7 +105,9 @@ public:
static void
unregisterPeerObjectCluster(const string& key);
- static void clear();
+ static void unregisterAll();
+
+ static void unregister(const string& key);
};
#define PEER_STORAGE(btContext) \
diff --git a/src/BtRuntime.h b/src/BtRuntime.h
index 4b58f748..55644bc6 100644
--- a/src/BtRuntime.h
+++ b/src/BtRuntime.h
@@ -46,12 +46,14 @@ private:
int32_t port;
bool halt;
int32_t connections;
+ bool _ready;
public:
BtRuntime():
uploadLengthAtStartup(0),
port(0),
halt(false),
- connections(0)
+ connections(0),
+ _ready(false)
{}
~BtRuntime() {}
@@ -83,7 +85,11 @@ public:
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;
diff --git a/src/BtSetup.cc b/src/BtSetup.cc
new file mode 100644
index 00000000..d9a70fbb
--- /dev/null
+++ b/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;
+}
diff --git a/src/DefaultFileAllocator.h b/src/BtSetup.h
index 1a74939a..12636eee 100644
--- a/src/DefaultFileAllocator.h
+++ b/src/BtSetup.h
@@ -32,20 +32,22 @@
* files in the program, then also delete it here.
*/
/* 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_
diff --git a/src/ByteArrayDiskWriter.cc b/src/ByteArrayDiskWriter.cc
index 0e8c2151..864d167c 100644
--- a/src/ByteArrayDiskWriter.cc
+++ b/src/ByteArrayDiskWriter.cc
@@ -38,34 +38,35 @@
ByteArrayDiskWriter::ByteArrayDiskWriter() {
}
-ByteArrayDiskWriter::~ByteArrayDiskWriter() {
- closeFile();
-}
+ByteArrayDiskWriter::~ByteArrayDiskWriter() {}
-void ByteArrayDiskWriter::clear() {
+void ByteArrayDiskWriter::clear()
+{
buf.str("");
}
void ByteArrayDiskWriter::initAndOpenFile(const string& filename,
- int64_t totalLength) {
+ int64_t totalLength)
+{
clear();
}
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,
- int64_t totalLength) {
+ int64_t totalLength)
+{
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) {
buf.seekg(0, ios::end);
for(int32_t i = size(); i < position; ++i) {
@@ -74,12 +75,13 @@ void ByteArrayDiskWriter::writeData(const char* data, int32_t dataLength, int64_
} else {
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.read(data, len);
+ buf.read(reinterpret_cast<char*>(data), len);
// TODO we have to call buf.clear() here? YES
buf.clear();
return buf.gcount();
diff --git a/src/ByteArrayDiskWriter.h b/src/ByteArrayDiskWriter.h
index a3583552..f35b4366 100644
--- a/src/ByteArrayDiskWriter.h
+++ b/src/ByteArrayDiskWriter.h
@@ -55,9 +55,8 @@ public:
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
virtual void truncate(int64_t length) {}
diff --git a/src/ByteArrayDiskWriterFactory.h b/src/ByteArrayDiskWriterFactory.h
new file mode 100644
index 00000000..2c72194e
--- /dev/null
+++ b/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_
diff --git a/src/CheckIntegrityCommand.cc b/src/CheckIntegrityCommand.cc
index 5b1231cd..a2d4aad1 100644
--- a/src/CheckIntegrityCommand.cc
+++ b/src/CheckIntegrityCommand.cc
@@ -33,6 +33,9 @@
*/
/* copyright --> */
#include "CheckIntegrityCommand.h"
+#include "CheckIntegrityMan.h"
+#include "CheckIntegrityEntry.h"
+#include "RequestGroup.h"
#include "FileAllocationEntry.h"
#include "InitiateConnectionCommandFactory.h"
#include "DlAbortEx.h"
@@ -40,7 +43,7 @@
#include "DownloadCommand.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),
_entry(entry)
{
@@ -54,25 +57,16 @@ CheckIntegrityCommand::~CheckIntegrityCommand()
bool CheckIntegrityCommand::executeInternal()
{
+ if(_requestGroup->isHaltRequested()) {
+ return true;
+ }
_entry->validateChunk();
if(_entry->finished()) {
+ _entry->updatePieceStorage();
if(_requestGroup->downloadFinished()) {
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 {
- 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;
} else {
@@ -84,12 +78,6 @@ bool CheckIntegrityCommand::executeInternal()
bool CheckIntegrityCommand::handleException(Exception* e)
{
logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid);
- delete e;
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;
}
diff --git a/src/CheckIntegrityCommand.h b/src/CheckIntegrityCommand.h
index e66fe93d..c924b8b1 100644
--- a/src/CheckIntegrityCommand.h
+++ b/src/CheckIntegrityCommand.h
@@ -36,16 +36,17 @@
#define _D_CHECK_INTEGRITY_COMMAND_H_
#include "RealtimeCommand.h"
-#include "IteratableChunkChecksumValidator.h"
-#include "CheckIntegrityEntry.h"
#include "TimeA2.h"
+class CheckIntegrityEntry;
+extern typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
+
class CheckIntegrityCommand : public RealtimeCommand {
private:
CheckIntegrityEntryHandle _entry;
Time _timer;
public:
- CheckIntegrityCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, const CheckIntegrityEntryHandle& entry);
+ CheckIntegrityCommand(int32_t cuid, RequestGroup* requestGroup, DownloadEngine* e, const CheckIntegrityEntryHandle& entry);
virtual ~CheckIntegrityCommand();
diff --git a/src/CheckIntegrityEntry.cc b/src/CheckIntegrityEntry.cc
index d4ae1e7c..0377b907 100644
--- a/src/CheckIntegrityEntry.cc
+++ b/src/CheckIntegrityEntry.cc
@@ -34,33 +34,64 @@
/* copyright --> */
#include "CheckIntegrityEntry.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()
{
_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();
}
-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()
{
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;
}
+
+void CheckIntegrityEntry::updatePieceStorage()
+{
+ _validator->updatePieceStorage();
+}
diff --git a/src/CheckIntegrityEntry.h b/src/CheckIntegrityEntry.h
index b52b7ce6..e82076d1 100644
--- a/src/CheckIntegrityEntry.h
+++ b/src/CheckIntegrityEntry.h
@@ -36,29 +36,37 @@
#define _D_CHECK_INTEGRITY_ENTRY_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:
IteratableChunkChecksumValidatorHandle _validator;
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 validateChunk();
+
+ void updatePieceStorage();
+
+ virtual Commands prepareForNextAction(DownloadEngine* e) = 0;
};
typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
diff --git a/src/CheckIntegrityMan.cc b/src/CheckIntegrityMan.cc
new file mode 100644
index 00000000..dcb7d157
--- /dev/null
+++ b/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();
+}
diff --git a/src/CheckIntegrityMan.h b/src/CheckIntegrityMan.h
index bc0297ae..1e07cd78 100644
--- a/src/CheckIntegrityMan.h
+++ b/src/CheckIntegrityMan.h
@@ -36,43 +36,26 @@
#define _D_CHECK_INTEGRITY_MAN_H_
#include "common.h"
-#include "CheckIntegrityEntry.h"
+
+class CheckIntegrityEntry;
+extern typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
+extern typedef deque<CheckIntegrityEntryHandle> CheckIntegrityEntries;
class CheckIntegrityMan {
private:
CheckIntegrityEntries _checkIntegrityEntries;
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;
diff --git a/src/ChecksumCommand.cc b/src/ChecksumCommand.cc
index 0d2166c4..b2ec0964 100644
--- a/src/ChecksumCommand.cc
+++ b/src/ChecksumCommand.cc
@@ -39,9 +39,11 @@
void ChecksumCommand::initValidator()
{
_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()) {
// insufficient checksums.
throw new DlAbortEx(EX_INSUFFICIENT_CHECKSUM);
@@ -51,6 +53,9 @@ void ChecksumCommand::initValidator()
bool ChecksumCommand::executeInternal()
{
+ if(_e->isHaltRequested()) {
+ return true;
+ }
_validator->validateChunk();
if(_validator->finished()) {
if(_requestGroup->downloadFinished()) {
@@ -70,7 +75,6 @@ bool ChecksumCommand::executeInternal()
bool ChecksumCommand::handleException(Exception* e)
{
logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid);
- delete e;
logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str());
// 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
diff --git a/src/ChecksumCommand.h b/src/ChecksumCommand.h
index 06260380..f460f1a8 100644
--- a/src/ChecksumCommand.h
+++ b/src/ChecksumCommand.h
@@ -47,12 +47,12 @@ public:
RealtimeCommand(cuid, requestGroup, e),
_validator(0)
{
- ++_requestGroup->numConnection;
+ _requestGroup->increaseNumCommand();
}
virtual ~ChecksumCommand()
{
- --_requestGroup->numConnection;
+ _requestGroup->decreaseNumCommand();
}
void initValidator();
diff --git a/src/ChunkChecksum.h b/src/ChunkChecksum.h
index 9b91b351..e9dfbee2 100644
--- a/src/ChunkChecksum.h
+++ b/src/ChunkChecksum.h
@@ -79,6 +79,11 @@ public:
return "";
}
}
+
+ const Strings& getChecksums() const
+ {
+ return _checksums;
+ }
int32_t getChecksumLength() const
{
diff --git a/src/ChunkChecksumValidator.cc b/src/ChunkChecksumValidator.cc
index 9e9b65ff..b6a5a5bf 100644
--- a/src/ChunkChecksumValidator.cc
+++ b/src/ChunkChecksumValidator.cc
@@ -38,6 +38,7 @@
void ChunkChecksumValidator::validate()
{
+ /*
if(!_validator->canValidate()) {
// insufficient checksums.
logger->error(MSG_INSUFFICIENT_CHECKSUM,
@@ -63,4 +64,5 @@ void ChunkChecksumValidator::validate()
}
fileAllocationMonitor->setCurrentValue(numChecksum);
fileAllocationMonitor->showProgress();
+*/
}
diff --git a/src/ConsoleDownloadEngine.cc b/src/ConsoleDownloadEngine.cc
deleted file mode 100644
index 5237ba16..00000000
--- a/src/ConsoleDownloadEngine.cc
+++ /dev/null
@@ -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));
-}
diff --git a/src/ConsoleStatCalc.cc b/src/ConsoleStatCalc.cc
new file mode 100644
index 00000000..d30ce945
--- /dev/null
+++ b/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;
+}
diff --git a/src/TrackerSegmentManFactory.h b/src/ConsoleStatCalc.h
index dcec0096..f221509b 100644
--- a/src/TrackerSegmentManFactory.h
+++ b/src/ConsoleStatCalc.h
@@ -32,20 +32,24 @@
* files in the program, then also delete it here.
*/
/* 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:
- 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_
diff --git a/src/CopyDiskAdaptor.cc b/src/CopyDiskAdaptor.cc
index 1cc92bfb..a08b0808 100644
--- a/src/CopyDiskAdaptor.cc
+++ b/src/CopyDiskAdaptor.cc
@@ -36,13 +36,17 @@
#include "Util.h"
#include "message.h"
-void CopyDiskAdaptor::onDownloadComplete() {
+void CopyDiskAdaptor::onDownloadComplete()
+ throw(DlAbortEx*)
+{
closeFile();
fixFilename();
openFile();
}
-void CopyDiskAdaptor::fixFilename() {
+void CopyDiskAdaptor::fixFilename()
+ throw(DlAbortEx*)
+{
int64_t offset = 0;
for(FileEntries::iterator itr = fileEntries.begin();
itr != fileEntries.end(); itr++) {
@@ -59,6 +63,7 @@ void CopyDiskAdaptor::fixFilename() {
}
}
-string CopyDiskAdaptor::getFilePath() {
+string CopyDiskAdaptor::getFilePath()
+{
return storeDir+"/"+tempFilename;
}
diff --git a/src/CopyDiskAdaptor.h b/src/CopyDiskAdaptor.h
index af6effdf..22b3fec9 100644
--- a/src/CopyDiskAdaptor.h
+++ b/src/CopyDiskAdaptor.h
@@ -36,13 +36,14 @@
#define _D_COPY_DISK_ADAPTOR_H_
#include "AbstractSingleDiskAdaptor.h"
+#include "DlAbortEx.h"
class CopyDiskAdaptor : public AbstractSingleDiskAdaptor {
private:
string tempFilename;
string topDir;
- void fixFilename();
+ void fixFilename() throw(DlAbortEx*);
public:
CopyDiskAdaptor() {}
@@ -50,7 +51,7 @@ public:
virtual string getFilePath();
- virtual void onDownloadComplete();
+ virtual void onDownloadComplete() throw(DlAbortEx*);
// tempFilename is relative to storeDir
void setTempFilename(const string& tempFilename) {
diff --git a/src/DefaultBtContext.cc b/src/DefaultBtContext.cc
index 17bc22a2..39a5a8cf 100644
--- a/src/DefaultBtContext.cc
+++ b/src/DefaultBtContext.cc
@@ -42,9 +42,10 @@
#include "Util.h"
#include "MessageDigestHelper.h"
#include "a2netcompat.h"
+#include "AnnounceTier.h"
#include <libgen.h>
-DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-") {}
+DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-"), _ownerRequestGroup(0) {}
DefaultBtContext::~DefaultBtContext() {}
@@ -248,6 +249,11 @@ int32_t DefaultBtContext::getNumPieces() const {
return numPieces;
}
+string DefaultBtContext::getActualBasePath() const
+{
+ return _dir+"/"+name;
+}
+
Integers DefaultBtContext::computeFastSet(const string& ipaddr, int32_t fastSetSize)
{
Integers fastSet;
diff --git a/src/DefaultBtContext.h b/src/DefaultBtContext.h
index 36c9a543..609cad18 100644
--- a/src/DefaultBtContext.h
+++ b/src/DefaultBtContext.h
@@ -59,6 +59,8 @@ private:
string _peerIdPrefix;
AnnounceTiers announceTiers;
+ RequestGroup* _ownerRequestGroup;
+
void clear();
void extractPieceHash(const unsigned char* hashData,
int32_t hashDataLength,
@@ -90,6 +92,11 @@ private:
virtual FileEntries getFileEntries() const;
+ virtual string getPieceHashAlgo() const
+ {
+ return "sha1";
+ }
+
virtual AnnounceTiers getAnnounceTiers() const;
virtual void load(const string& torrentFile);
@@ -100,6 +107,8 @@ private:
virtual int32_t getNumPieces() const;
+ virtual string getActualBasePath() const;
+
virtual const unsigned char* getPeerId() {
if(peerId == "") {
peerId = generatePeerId();
@@ -109,6 +118,11 @@ private:
virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize);
+ virtual RequestGroup* getOwnerRequestGroup()
+ {
+ return _ownerRequestGroup;
+ }
+
string generatePeerId() const;
void setPeerIdPrefix(const string& peerIdPrefix)
@@ -126,7 +140,11 @@ private:
{
this->numPieces = numPieces;
}
-
+
+ void setOwnerRequestGroup(RequestGroup* owner)
+ {
+ _ownerRequestGroup = owner;
+ }
};
typedef SharedHandle<DefaultBtContext> DefaultBtContextHandle;
diff --git a/src/DefaultBtProgressInfoFile.cc b/src/DefaultBtProgressInfoFile.cc
index 7c0c9a77..955d11bb 100644
--- a/src/DefaultBtProgressInfoFile.cc
+++ b/src/DefaultBtProgressInfoFile.cc
@@ -33,6 +33,9 @@
*/
/* copyright --> */
#include "DefaultBtProgressInfoFile.h"
+#include "DownloadContext.h"
+#include "PieceStorage.h"
+#include "Option.h"
#include "BtRegistry.h"
#include "LogFactory.h"
#include "prefs.h"
@@ -41,143 +44,245 @@
#include "File.h"
#include "Util.h"
#include "a2io.h"
+#include <fstream>
#include <errno.h>
-DefaultBtProgressInfoFile::DefaultBtProgressInfoFile(const BtContextHandle& btContext,
+DefaultBtProgressInfoFile::DefaultBtProgressInfoFile(const DownloadContextHandle& dctx,
+ const PieceStorageHandle& pieceStorage,
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() {}
+bool DefaultBtProgressInfoFile::isTorrentDownload()
+{
+ return !BtContextHandle(_dctx).isNull();
+}
+
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 {
- 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,
- 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,
- 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* savedBitfield = 0;
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;
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;
+ 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() {
if(exists()) {
- File f(filename);
+ File f(_filename);
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() {
- File f(filename);
+ File f(_filename);
if(f.isFile()) {
- logger->info(MSG_SEGMENT_FILE_EXISTS, filename.c_str());
+ _logger->info(MSG_SEGMENT_FILE_EXISTS, _filename.c_str());
return true;
} 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;
}
}
diff --git a/src/DefaultBtProgressInfoFile.h b/src/DefaultBtProgressInfoFile.h
index 201900dd..4ca0e5e6 100644
--- a/src/DefaultBtProgressInfoFile.h
+++ b/src/DefaultBtProgressInfoFile.h
@@ -36,49 +36,33 @@
#define _D_DEFAULT_BT_PROGRESS_INFO_FILE_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 {
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:
- DefaultBtProgressInfoFile(const BtContextHandle& btContext,
+ DefaultBtProgressInfoFile(const DownloadContextHandle& btContext,
+ const PieceStorageHandle& pieceStorage,
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 void save();
diff --git a/src/DefaultDiskWriter.cc b/src/DefaultDiskWriter.cc
index 4ddef412..4334391e 100644
--- a/src/DefaultDiskWriter.cc
+++ b/src/DefaultDiskWriter.cc
@@ -33,10 +33,7 @@
*/
/* copyright --> */
#include "DefaultDiskWriter.h"
-#include "DlAbortEx.h"
#include "message.h"
-#include "DefaultFileAllocator.h"
-#include "GlowFileAllocator.h"
#include "prefs.h"
#include "Util.h"
#include <errno.h>
@@ -48,38 +45,7 @@ DefaultDiskWriter::~DefaultDiskWriter() {}
void DefaultDiskWriter::initAndOpenFile(const string& filename,
int64_t totalLength)
+ throw(DlAbortEx*)
{
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;
}
diff --git a/src/DefaultDiskWriter.h b/src/DefaultDiskWriter.h
index 5668d9a1..e5516181 100644
--- a/src/DefaultDiskWriter.h
+++ b/src/DefaultDiskWriter.h
@@ -37,6 +37,7 @@
#include "AbstractDiskWriter.h"
#include "Option.h"
+#include "DlAbortEx.h"
class DefaultDiskWriter:public AbstractDiskWriter {
public:
@@ -45,9 +46,7 @@ public:
virtual ~DefaultDiskWriter();
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;
diff --git a/src/DefaultDiskWriterFactory.h b/src/DefaultDiskWriterFactory.h
new file mode 100644
index 00000000..1a8a1156
--- /dev/null
+++ b/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_
diff --git a/src/DefaultPeerStorage.cc b/src/DefaultPeerStorage.cc
index dee82851..b0782b11 100644
--- a/src/DefaultPeerStorage.cc
+++ b/src/DefaultPeerStorage.cc
@@ -192,6 +192,8 @@ TransferStat DefaultPeerStorage::calculateStat() {
TransferStat stat = calStat.getTransferStat();
stat.sessionDownloadLength += removedPeerSessionDownloadLength;
stat.sessionUploadLength += removedPeerSessionUploadLength;
+ stat.setAllTimeUploadLength(btRuntime->getUploadLengthAtStartup()+
+ stat.getSessionUploadLength());
return stat;
}
diff --git a/src/DefaultPieceStorage.cc b/src/DefaultPieceStorage.cc
index 5afb64e7..7435fbce 100644
--- a/src/DefaultPieceStorage.cc
+++ b/src/DefaultPieceStorage.cc
@@ -33,29 +33,31 @@
*/
/* copyright --> */
#include "DefaultPieceStorage.h"
+#include "DownloadContext.h"
+#include "Piece.h"
+#include "Peer.h"
#include "LogFactory.h"
#include "prefs.h"
#include "DirectDiskAdaptor.h"
#include "MultiDiskAdaptor.h"
#include "CopyDiskAdaptor.h"
-#include "DefaultDiskWriter.h"
-#include "DlAbortEx.h"
+#include "DiskWriter.h"
#include "BitfieldManFactory.h"
-#include "FileAllocationMonitor.h"
-#include "DiskAdaptorWriter.h"
-#include "ChunkChecksumValidator.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),
+ _diskWriterFactory(new DefaultDiskWriterFactory()),
endGamePieceNum(END_GAME_PIECE_NUM),
option(option)
{
bitfieldMan =
BitfieldManFactory::getFactoryInstance()->
- createBitfieldMan(btContext->getPieceLength(),
- btContext->getTotalLength());
+ createBitfieldMan(downloadContext->getPieceLength(),
+ downloadContext->getTotalLength());
logger = LogFactory::getInstance();
}
@@ -63,16 +65,19 @@ DefaultPieceStorage::~DefaultPieceStorage() {
delete bitfieldMan;
}
-bool DefaultPieceStorage::hasMissingPiece(const PeerHandle& peer) {
+bool DefaultPieceStorage::hasMissingPiece(const PeerHandle& peer)
+{
return bitfieldMan->hasMissingPiece(peer->getBitfield(),
peer->getBitfieldLength());
}
-bool DefaultPieceStorage::isEndGame() {
+bool DefaultPieceStorage::isEndGame()
+{
return bitfieldMan->countMissingBlock() <= endGamePieceNum;
}
-int32_t DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer) {
+int32_t DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer)
+{
int32_t index = -1;
if(isEndGame()) {
index = bitfieldMan->getMissingIndex(peer->getBitfield(),
@@ -84,7 +89,8 @@ int32_t DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer) {
return index;
}
-PieceHandle DefaultPieceStorage::checkOutPiece(int32_t index) {
+PieceHandle DefaultPieceStorage::checkOutPiece(int32_t index)
+{
if(index == -1) {
return 0;
}
@@ -104,7 +110,8 @@ PieceHandle DefaultPieceStorage::checkOutPiece(int32_t index) {
* Newly instantiated piece is not added to usedPieces.
* 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()) {
PieceHandle piece = findUsedPiece(index);
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);
}
@@ -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(),
usedPieces.end(),
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);
return checkOutPiece(index);
}
-int32_t DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer) {
+int32_t DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer)
+{
int32_t index = -1;
if(peer->isFastExtensionEnabled() && peer->countFastSet() > 0) {
BitfieldMan tempBitfield(bitfieldMan->getBlockLength(),
@@ -172,12 +183,28 @@ int32_t DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer) {
return index;
}
-PieceHandle DefaultPieceStorage::getMissingFastPiece(const PeerHandle& peer) {
+PieceHandle DefaultPieceStorage::getMissingFastPiece(const PeerHandle& peer)
+{
int32_t index = getMissingFastPieceIndex(peer);
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()) {
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;
if(toDelete <= 0) {
return;
@@ -204,7 +232,8 @@ void DefaultPieceStorage::reduceUsedPieces(int32_t delMax) {
}
int32_t DefaultPieceStorage::deleteUsedPiecesByFillRate(int32_t fillRate,
- int32_t toDelete) {
+ int32_t toDelete)
+{
int32_t deleted = 0;
for(Pieces::iterator itr = usedPieces.begin();
itr != usedPieces.end() && deleted < toDelete;) {
@@ -224,7 +253,8 @@ int32_t DefaultPieceStorage::deleteUsedPiecesByFillRate(int32_t fillRate,
return deleted;
}
-void DefaultPieceStorage::completePiece(const PieceHandle& piece) {
+void DefaultPieceStorage::completePiece(const PieceHandle& piece)
+{
if(piece.isNull()) {
return;
}
@@ -250,17 +280,20 @@ void DefaultPieceStorage::completePiece(const PieceHandle& piece) {
}
}
-bool DefaultPieceStorage::isSelectiveDownloadingMode() {
+bool DefaultPieceStorage::isSelectiveDownloadingMode()
+{
return bitfieldMan->isFilterEnabled();
}
-void DefaultPieceStorage::finishSelectiveDownloadingMode() {
+void DefaultPieceStorage::finishSelectiveDownloadingMode()
+{
bitfieldMan->clearFilter();
diskAdaptor->addAllDownloadEntry();
}
// not unittested
-void DefaultPieceStorage::cancelPiece(const PieceHandle& piece) {
+void DefaultPieceStorage::cancelPiece(const PieceHandle& piece)
+{
if(piece.isNull()) {
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);
}
-int64_t DefaultPieceStorage::getTotalLength() {
+bool DefaultPieceStorage::isPieceUsed(int32_t index)
+{
+ return bitfieldMan->isUseBitSet(index);
+}
+
+int64_t DefaultPieceStorage::getTotalLength()
+{
return bitfieldMan->getTotalLength();
}
-int64_t DefaultPieceStorage::getFilteredTotalLength() {
+int64_t DefaultPieceStorage::getFilteredTotalLength()
+{
return bitfieldMan->getFilteredTotalLength();
}
-int64_t DefaultPieceStorage::getCompletedLength() {
+int64_t DefaultPieceStorage::getCompletedLength()
+{
return bitfieldMan->getCompletedLength();
}
-int64_t DefaultPieceStorage::getFilteredCompletedLength() {
+int64_t DefaultPieceStorage::getFilteredCompletedLength()
+{
return bitfieldMan->getFilteredCompletedLength();
}
// 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;
}
diskAdaptor->removeAllDownloadEntry();
@@ -309,7 +353,8 @@ void DefaultPieceStorage::setFileFilter(const Strings& filePaths) {
bitfieldMan->enableFilter();
}
-void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes) {
+void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes)
+{
Strings filePaths;
const FileEntries& entries = diskAdaptor->getFileEntries();
for(int32_t i = 0; i < (int32_t)entries.size(); i++) {
@@ -322,66 +367,77 @@ void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes) {
}
// not unittested
-void DefaultPieceStorage::clearFileFilter() {
+void DefaultPieceStorage::clearFileFilter()
+{
bitfieldMan->clearFilter();
diskAdaptor->addAllDownloadEntry();
}
// not unittested
-bool DefaultPieceStorage::downloadFinished() {
+bool DefaultPieceStorage::downloadFinished()
+{
return bitfieldMan->isFilteredAllBitSet();
}
// not unittested
-bool DefaultPieceStorage::allDownloadFinished() {
+bool DefaultPieceStorage::allDownloadFinished()
+{
return bitfieldMan->isAllBitSet();
}
// 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();
- multiDiskAdaptor->setPieceLength(btContext->getPieceLength());
- multiDiskAdaptor->setTopDir(btContext->getName());
+ multiDiskAdaptor->setPieceLength(downloadContext->getPieceLength());
+ multiDiskAdaptor->setTopDir(downloadContext->getName());
multiDiskAdaptor->setOption(option);
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->setFileEntries(btContext->getFileEntries());
+ diskAdaptor->setFileEntries(downloadContext->getFileEntries());
}
void DefaultPieceStorage::setBitfield(const unsigned char* bitfield,
- int32_t bitfieldLength) {
+ int32_t bitfieldLength)
+{
bitfieldMan->setBitfield(bitfield, bitfieldLength);
}
-int32_t DefaultPieceStorage::getBitfieldLength() {
+int32_t DefaultPieceStorage::getBitfieldLength()
+{
return bitfieldMan->getBitfieldLength();
}
-const unsigned char* DefaultPieceStorage::getBitfield() {
+const unsigned char* DefaultPieceStorage::getBitfield()
+{
return bitfieldMan->getBitfield();
}
@@ -389,17 +445,20 @@ DiskAdaptorHandle DefaultPieceStorage::getDiskAdaptor() {
return diskAdaptor;
}
-int32_t DefaultPieceStorage::getPieceLength(int32_t index) {
+int32_t DefaultPieceStorage::getPieceLength(int32_t 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);
haves.push_front(entry);
}
Integers DefaultPieceStorage::getAdvertisedPieceIndexes(int32_t myCuid,
- const Time& lastCheckTime) {
+ const Time& lastCheckTime)
+{
Integers indexes;
for(Haves::const_iterator itr = haves.begin(); itr != haves.end(); 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 =
find_if(haves.begin(), haves.end(), FindElapsedHave(elapsed));
if(itr != haves.end()) {
@@ -444,19 +504,33 @@ void DefaultPieceStorage::markAllPiecesDone()
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;
}
diff --git a/src/DefaultPieceStorage.h b/src/DefaultPieceStorage.h
index 97ae031e..9da473c2 100644
--- a/src/DefaultPieceStorage.h
+++ b/src/DefaultPieceStorage.h
@@ -36,13 +36,15 @@
#define _D_DEFAULT_PIECE_STORAGE_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
@@ -67,15 +69,15 @@ typedef deque<HaveEntry> Haves;
class DefaultPieceStorage : public PieceStorage {
private:
- BtContextHandle btContext;
+ DownloadContextHandle downloadContext;
BitfieldMan* bitfieldMan;
DiskAdaptorHandle diskAdaptor;
+ DiskWriterFactoryHandle _diskWriterFactory;
Pieces usedPieces;
int32_t endGamePieceNum;
Logger* logger;
const Option* option;
Haves haves;
- FileAllocatorHandle createFileAllocator();
int32_t getMissingPieceIndex(const PeerHandle& peer);
int32_t getMissingFastPieceIndex(const PeerHandle& peer);
@@ -85,7 +87,7 @@ private:
void deleteUsedPiece(const PieceHandle& piece);
PieceHandle findUsedPiece(int32_t index) const;
public:
- DefaultPieceStorage(BtContextHandle btContext, const Option* option);
+ DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option);
virtual ~DefaultPieceStorage();
virtual bool hasMissingPiece(const PeerHandle& peer);
@@ -94,6 +96,10 @@ public:
virtual PieceHandle getMissingFastPiece(const PeerHandle& peer);
+ virtual PieceHandle getMissingPiece();
+
+ virtual PieceHandle getMissingPiece(int32_t index);
+
virtual PieceHandle getPiece(int32_t index);
virtual void completePiece(const PieceHandle& piece);
@@ -102,6 +108,8 @@ public:
virtual bool hasPiece(int32_t index);
+ virtual bool isPieceUsed(int32_t index);
+
virtual int64_t getTotalLength();
virtual int64_t getFilteredTotalLength();
@@ -156,13 +164,24 @@ public:
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.
*/
void addUsedPiece(const PieceHandle& piece);
+ void setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory);
};
+typedef SharedHandle<DefaultPieceStorage> DefaultPieceStorageHandle;
+
#endif // _D_DEFAULT_PIECE_STORAGE_H_
diff --git a/src/DefaultSegmentManFactory.cc b/src/DefaultSegmentManFactory.cc
index 0719045d..00d66e9a 100644
--- a/src/DefaultSegmentManFactory.cc
+++ b/src/DefaultSegmentManFactory.cc
@@ -36,13 +36,14 @@
#include "prefs.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.
//segmentMan->ufilename = _option->get(PREF_OUT);
- segmentMan->option = _option;
+ //segmentMan->option = _option;
return segmentMan;
}
diff --git a/src/DefaultSegmentManFactory.h b/src/DefaultSegmentManFactory.h
index 0a8dad1d..e09d1b29 100644
--- a/src/DefaultSegmentManFactory.h
+++ b/src/DefaultSegmentManFactory.h
@@ -43,7 +43,8 @@ public:
virtual ~DefaultSegmentManFactory() {}
- virtual SegmentManHandle createNewInstance();
+ virtual SegmentManHandle createNewInstance(const DownloadContextHandle& dc,
+ const PieceStorageHandle& ps);
};
typedef SharedHandle<DefaultSegmentManFactory> DefaultSegmentManFactoryHandle;
diff --git a/src/FileAllocationMonitor.cc b/src/Dependency.h
index 7a68df7b..0851f66c 100644
--- a/src/FileAllocationMonitor.cc
+++ b/src/Dependency.h
@@ -32,6 +32,18 @@
* files in the program, then also delete it here.
*/
/* 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_
diff --git a/src/DirectDiskAdaptor.cc b/src/DirectDiskAdaptor.cc
index 46941558..096d27dd 100644
--- a/src/DirectDiskAdaptor.cc
+++ b/src/DirectDiskAdaptor.cc
@@ -34,11 +34,14 @@
/* copyright --> */
#include "DirectDiskAdaptor.h"
-string DirectDiskAdaptor::getFilePath() {
+string DirectDiskAdaptor::getFilePath()
+{
return storeDir+"/"+fileEntries.front()->getPath();
}
-void DirectDiskAdaptor::onDownloadComplete() {
+void DirectDiskAdaptor::onDownloadComplete()
+ throw(DlAbortEx*)
+{
closeFile();
openFile();
}
diff --git a/src/DirectDiskAdaptor.h b/src/DirectDiskAdaptor.h
index 16b01f36..5fcb37fd 100644
--- a/src/DirectDiskAdaptor.h
+++ b/src/DirectDiskAdaptor.h
@@ -36,6 +36,7 @@
#define _D_DIRECT_DISK_ADAPTOR_H_
#include "AbstractSingleDiskAdaptor.h"
+#include "DlAbortEx.h"
class DirectDiskAdaptor : public AbstractSingleDiskAdaptor {
public:
@@ -44,7 +45,7 @@ public:
virtual string getFilePath();
- virtual void onDownloadComplete();
+ virtual void onDownloadComplete() throw(DlAbortEx*);
};
typedef SharedHandle<DirectDiskAdaptor> DirectDiskAdaptorHandle;
diff --git a/src/DiskAdaptor.cc b/src/DiskAdaptor.cc
index 4aa59c54..0a12df6a 100644
--- a/src/DiskAdaptor.cc
+++ b/src/DiskAdaptor.cc
@@ -33,7 +33,6 @@
*/
/* copyright --> */
#include "DiskAdaptor.h"
-#include "DlAbortEx.h"
#include "LogFactory.h"
#include "message.h"
@@ -41,7 +40,9 @@ DiskAdaptor::DiskAdaptor():logger(LogFactory::getInstance()) {}
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();
itr != fileEntries.end(); itr++) {
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());
}
-bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath) {
+bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath)
+{
for(FileEntries::iterator itr = fileEntries.begin();
itr != fileEntries.end(); itr++) {
if((*itr)->getPath() == fileEntryPath) {
@@ -62,7 +64,8 @@ bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath) {
return false;
}
-bool DiskAdaptor::addDownloadEntry(int index) {
+bool DiskAdaptor::addDownloadEntry(int index)
+{
if(fileEntries.size() <= (unsigned int)index) {
return false;
}
@@ -70,14 +73,16 @@ bool DiskAdaptor::addDownloadEntry(int index) {
return true;
}
-void DiskAdaptor::addAllDownloadEntry() {
+void DiskAdaptor::addAllDownloadEntry()
+{
for(FileEntries::iterator itr = fileEntries.begin();
itr != fileEntries.end(); itr++) {
(*itr)->setRequested(true);
}
}
-void DiskAdaptor::removeAllDownloadEntry() {
+void DiskAdaptor::removeAllDownloadEntry()
+{
for(FileEntries::iterator itr = fileEntries.begin();
itr != fileEntries.end(); itr++) {
(*itr)->setRequested(false);
diff --git a/src/DiskAdaptor.h b/src/DiskAdaptor.h
index 5a1c6df1..b44b69db 100644
--- a/src/DiskAdaptor.h
+++ b/src/DiskAdaptor.h
@@ -35,11 +35,13 @@
#ifndef _D_DISK_ADAPTOR_H_
#define _D_DISK_ADAPTOR_H_
-#include "common.h"
+#include "BinaryStream.h"
#include "FileEntry.h"
#include "Logger.h"
+#include "FileAllocationIterator.h"
+#include "DlAbortEx.h"
-class DiskAdaptor {
+class DiskAdaptor:public BinaryStream {
protected:
string storeDir;
FileEntries fileEntries;
@@ -56,10 +58,6 @@ public:
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 bool fileExists() = 0;
@@ -68,11 +66,15 @@ public:
virtual int64_t size() const = 0;
+ // optional behavior
+ virtual void truncate(int64_t length) {}
+
void setFileEntries(const 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; }
@@ -87,6 +89,8 @@ public:
void setStoreDir(const string& storeDir) { this->storeDir = storeDir; }
const string& getStoreDir() const { return this->storeDir; }
+
+ virtual FileAllocationIteratorHandle fileAllocationIterator() = 0;
};
typedef SharedHandle<DiskAdaptor> DiskAdaptorHandle;
diff --git a/src/DiskWriter.h b/src/DiskWriter.h
index 5f0a93b5..f64808d6 100644
--- a/src/DiskWriter.h
+++ b/src/DiskWriter.h
@@ -35,15 +35,14 @@
#ifndef _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.
*
*/
-class DiskWriter {
+class DiskWriter:public BinaryStream {
public:
virtual ~DiskWriter() {}
/**
@@ -51,13 +50,14 @@ public:
* If the file exists, then it is truncated to 0 length.
* @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;
/**
* Closes this output stream.
*/
+ // TODO we have to examine the return value of close()
virtual void closeFile() = 0;
/**
@@ -68,26 +68,6 @@ public:
*/
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;
// Returns file length
diff --git a/src/GlowFileAllocator.h b/src/DiskWriterFactory.h
index a16af76b..07611bc0 100644
--- a/src/GlowFileAllocator.h
+++ b/src/DiskWriterFactory.h
@@ -32,20 +32,19 @@
* files in the program, then also delete it here.
*/
/* 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:
- 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_
diff --git a/src/DownloadCommand.cc b/src/DownloadCommand.cc
index 2de238d6..bbc9dfcb 100644
--- a/src/DownloadCommand.cc
+++ b/src/DownloadCommand.cc
@@ -33,16 +33,20 @@
*/
/* copyright --> */
#include "DownloadCommand.h"
+#include "SegmentMan.h"
+#include "PeerStat.h"
+#include "TransferEncoding.h"
+#include "DownloadContext.h"
#include "Util.h"
#include "DlRetryEx.h"
#include "DlAbortEx.h"
-#include "HttpInitiateConnectionCommand.h"
#include "InitiateConnectionCommandFactory.h"
#include "message.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>
DownloadCommand::DownloadCommand(int cuid,
@@ -80,17 +84,23 @@ bool DownloadCommand::executeInternal() {
socket->readData(buf, bufSize);
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);
} else {
int32_t infbufSize = 16*1024;
char infbuf[infbufSize];
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);
}
// calculate downloading speed
@@ -103,7 +113,7 @@ bool DownloadCommand::executeInternal() {
req->getHost().c_str());
}
}
- if(_requestGroup->getSegmentMan()->totalSize != 0 && bufSize == 0) {
+ if(_requestGroup->getTotalLength() != 0 && bufSize == 0) {
throw new DlRetryEx(EX_GOT_EOF);
}
if(!transferDecoder.isNull() && transferDecoder->finished()
@@ -112,11 +122,22 @@ bool DownloadCommand::executeInternal() {
if(!transferDecoder.isNull()) transferDecoder->end();
logger->info(MSG_SEGMENT_DOWNLOAD_COMPLETED, cuid);
_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
if(e->option->get(PREF_REALTIME_CHUNK_CHECKSUM) == V_TRUE) {
_requestGroup->getSegmentMan()->tryChunkChecksumValidation(segment, _requestGroup->getChunkChecksum());
}
#endif // ENABLE_MESSAGE_DIGEST
+ */
// this unit is going to download another segment.
return prepareForNextSegment();
} else {
@@ -127,7 +148,9 @@ bool DownloadCommand::executeInternal() {
}
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
if(!_requestGroup->getChecksum().isNull() &&
!_requestGroup->getChecksum()->isEmpty()) {
@@ -136,6 +159,7 @@ bool DownloadCommand::prepareForNextSegment() {
e->commands.push_back(command);
}
#endif // ENABLE_MESSAGE_DIGEST
+ */
return true;
} else {
// Merge segment with next segment, if segment.index+1 == nextSegment.index
@@ -143,15 +167,15 @@ bool DownloadCommand::prepareForNextSegment() {
while(1) {
SegmentHandle nextSegment =
_requestGroup->getSegmentMan()->getSegment(cuid,
- tempSegment->index+1);
+ tempSegment->getIndex()+1);
if(nextSegment.isNull()) {
break;
} else {
- if(nextSegment->writtenLength > 0) {
+ if(nextSegment->getWrittenLength() > 0) {
return prepareForRetry(0);
}
- nextSegment->writtenLength =
- tempSegment->writtenLength-tempSegment->length;
+ nextSegment->updateWrittenLength(tempSegment->getOverflowLength());
+ //tempSegment->writtenLength-tempSegment->length;
if(nextSegment->complete()) {
_requestGroup->getSegmentMan()->completeSegment(cuid, nextSegment);
tempSegment = nextSegment;
@@ -165,3 +189,8 @@ bool DownloadCommand::prepareForNextSegment() {
return prepareForRetry(0);
}
}
+
+void DownloadCommand::setTransferDecoder(const TransferEncodingHandle& transferDecoder)
+{
+ this->transferDecoder = transferDecoder;
+}
diff --git a/src/DownloadCommand.h b/src/DownloadCommand.h
index c8176dcb..0e675d35 100644
--- a/src/DownloadCommand.h
+++ b/src/DownloadCommand.h
@@ -36,11 +36,11 @@
#define _D_DOWNLOAD_COMMAND_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 {
private:
@@ -62,10 +62,7 @@ public:
const SocketHandle& s);
virtual ~DownloadCommand();
- void setTransferDecoder(const TransferEncodingHandle& transferDecoder)
- {
- this->transferDecoder = transferDecoder;
- }
+ void setTransferDecoder(const TransferEncodingHandle& transferDecoder);
void setMaxDownloadSpeedLimit(int32_t maxDownloadSpeedLimit) {
this->maxDownloadSpeedLimit = maxDownloadSpeedLimit;
diff --git a/src/DownloadContext.h b/src/DownloadContext.h
new file mode 100644
index 00000000..9d70af11
--- /dev/null
+++ b/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_
diff --git a/src/DownloadEngine.cc b/src/DownloadEngine.cc
index 62dd7637..548b2d57 100644
--- a/src/DownloadEngine.cc
+++ b/src/DownloadEngine.cc
@@ -33,6 +33,15 @@
*/
/* copyright --> */
#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 "LogFactory.h"
#include "TimeA2.h"
@@ -41,11 +50,38 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
+#include <signal.h>
#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()),
+ _statCalc(0),
+ _haltRequested(false),
noWait(false),
_requestGroupMan(0),
_fileAllocationMan(0)
@@ -83,7 +119,6 @@ void DownloadEngine::executeCommand(Command::STATUS statusFilter)
}
void DownloadEngine::run() {
- initStatistics();
Time cp;
cp.setTimeInSec(0);
Commands activeCommands;
@@ -232,6 +267,38 @@ bool DownloadEngine::deleteSocketForWriteCheck(const SocketHandle& socket,
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
bool DownloadEngine::addNameResolverCheck(const NameResolverHandle& resolver,
Command* command) {
@@ -262,4 +329,10 @@ bool DownloadEngine::deleteNameResolverCheck(const NameResolverHandle& resolver,
return true;
}
}
+
+void DownloadEngine::addCommand(const Commands& commands)
+{
+ this->commands.insert(this->commands.end(), commands.begin(), commands.end());
+}
+
#endif // ENABLE_ASYNC_DNS
diff --git a/src/DownloadEngine.h b/src/DownloadEngine.h
index 2ce84dcb..a1486b66 100644
--- a/src/DownloadEngine.h
+++ b/src/DownloadEngine.h
@@ -35,21 +35,27 @@
#ifndef _D_DOWNLOAD_ENGINE_H_
#define _D_DOWNLOAD_ENGINE_H_
-#include "Command.h"
-#include "Socket.h"
-#include "SegmentMan.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
-# include "CheckIntegrityMan.h"
+class CheckIntegrityMan;
+extern typedef SharedHandle<CheckIntegrityMan> CheckIntegrityManHandle;
#endif // ENABLE_MESSAGE_DIGEST
-typedef deque<SocketHandle> Sockets;
-
class SocketEntry {
public:
enum TYPE {
@@ -63,15 +69,9 @@ public:
public:
SocketEntry(const SocketHandle& socket,
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;
@@ -83,14 +83,9 @@ public:
Command* command;
public:
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;
@@ -108,16 +103,26 @@ private:
fd_set wfdset;
int32_t fdmax;
+ const Logger* logger;
+
+ StatCalcHandle _statCalc;
+
+ bool _haltRequested;
+
void shortSleep() const;
bool addSocket(const SocketEntry& socketEntry);
bool deleteSocket(const SocketEntry& socketEntry);
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:
bool noWait;
Commands commands;
@@ -152,11 +157,19 @@ public:
Command* command);
#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_
diff --git a/src/DownloadEngineFactory.cc b/src/DownloadEngineFactory.cc
index 2c8f5b24..b3905981 100644
--- a/src/DownloadEngineFactory.cc
+++ b/src/DownloadEngineFactory.cc
@@ -33,46 +33,31 @@
*/
/* copyright --> */
#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 "DefaultDiskWriter.h"
-#include "InitiateConnectionCommandFactory.h"
#include "Util.h"
-#include "FileAllocator.h"
-#include "FileAllocationMonitor.h"
-#include "FillRequestGroupCommand.h"
#include "CUIDCounter.h"
+#include "FillRequestGroupCommand.h"
#include "FileAllocationDispatcherCommand.h"
-#include "FileAllocationMan.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 reservedSet;
if(op->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS) < (int32_t)requestGroups.size()) {
@@ -83,109 +68,24 @@ DownloadEngineFactory::newConsoleEngine(const Option* op,
workingSet = requestGroups;
}
- ConsoleDownloadEngine* e = new ConsoleDownloadEngine();
+ DownloadEngineHandle e = new DownloadEngine();
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);
e->_requestGroupMan = requestGroupMan;
e->_fileAllocationMan = new FileAllocationMan();
#ifdef ENABLE_MESSAGE_DIGEST
e->_checkIntegrityMan = new CheckIntegrityMan();
#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 =
- new PeerListenCommand(CUIDCounterSingletonHolder::instance()->newID(),
- te, btContext);
+ new PeerListenCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get());
int32_t port;
int32_t listenPort = op->getAsInt(PREF_LISTEN_PORT);
if(listenPort == -1) {
@@ -194,48 +94,13 @@ DownloadEngineFactory::newTorrentConsoleEngine(const BtContextHandle& btContext,
port = listenCommand->bindPort(listenPort, listenPort);
}
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
diff --git a/src/DownloadEngineFactory.h b/src/DownloadEngineFactory.h
index f9d11e5d..59c41712 100644
--- a/src/DownloadEngineFactory.h
+++ b/src/DownloadEngineFactory.h
@@ -36,28 +36,23 @@
#define _D_DOWNLOAD_ENGINE_FACTORY_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 {
+private:
+ const Logger* _logger;
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_
diff --git a/src/File.cc b/src/File.cc
index 342b91ca..0796e1e0 100644
--- a/src/File.cc
+++ b/src/File.cc
@@ -37,6 +37,11 @@
#include "a2io.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() {}
@@ -140,3 +145,21 @@ bool File::isDir(const string& filename)
{
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;
+ }
+}
diff --git a/src/File.h b/src/File.h
index 27cd386a..36b93093 100644
--- a/src/File.h
+++ b/src/File.h
@@ -96,6 +96,8 @@ public:
string getDirname() const;
static bool isDir(const string& filename);
+
+ bool renameTo(const string& dest);
};
#endif // _D_FILE_H_
diff --git a/src/FileAllocationCommand.cc b/src/FileAllocationCommand.cc
index 554086d8..01a24d65 100644
--- a/src/FileAllocationCommand.cc
+++ b/src/FileAllocationCommand.cc
@@ -33,45 +33,48 @@
*/
/* copyright --> */
#include "FileAllocationCommand.h"
-#include "InitiateConnectionCommandFactory.h"
+#include "FileAllocationMan.h"
+#include "FileAllocationEntry.h"
#include "message.h"
#include "DownloadCommand.h"
#include "prefs.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()
{
- _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)
{
logger->error(MSG_FILE_ALLOCATION_FAILURE, e, cuid);
- delete e;
logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str());
return true;
}
diff --git a/src/FileAllocationCommand.h b/src/FileAllocationCommand.h
index 84dfe652..371c6091 100644
--- a/src/FileAllocationCommand.h
+++ b/src/FileAllocationCommand.h
@@ -37,16 +37,19 @@
#include "RealtimeCommand.h"
#include "TimeA2.h"
-#include "FileAllocationEntry.h"
+
+class FileAllocationEntry;
+extern typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;
+class Exception;
class FileAllocationCommand : public RealtimeCommand {
private:
FileAllocationEntryHandle _fileAllocationEntry;
Time _timer;
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();
diff --git a/src/FileAllocationDispatcherCommand.cc b/src/FileAllocationDispatcherCommand.cc
index 8f328bbf..146d33fc 100644
--- a/src/FileAllocationDispatcherCommand.cc
+++ b/src/FileAllocationDispatcherCommand.cc
@@ -33,22 +33,35 @@
*/
/* copyright --> */
#include "FileAllocationDispatcherCommand.h"
+#include "DownloadEngine.h"
+#include "RequestGroupMan.h"
+#include "FileAllocationMan.h"
+#include "FileAllocationEntry.h"
#include "FileAllocationCommand.h"
#include "message.h"
+#include "CUIDCounter.h"
+
+FileAllocationDispatcherCommand::FileAllocationDispatcherCommand(int32_t cuid, DownloadEngine* e):
+ Command(cuid), _e(e)
+{
+ setStatusRealtime();
+}
+
+FileAllocationDispatcherCommand::~FileAllocationDispatcherCommand() {}
bool FileAllocationDispatcherCommand::execute()
{
- if(_e->_requestGroupMan->downloadFinished()) {
+ if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
return true;
}
-
if(!_e->_fileAllocationMan->isFileAllocationBeingExecuted() &&
_e->_fileAllocationMan->nextFileAllocationEntryExists()) {
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 =
- new FileAllocationCommand(entry->getCUID(),
+ new FileAllocationCommand(newCUID,
entry->getRequestGroup(),
_e,
entry);
diff --git a/src/FileAllocationDispatcherCommand.h b/src/FileAllocationDispatcherCommand.h
index e52681d6..892daed2 100644
--- a/src/FileAllocationDispatcherCommand.h
+++ b/src/FileAllocationDispatcherCommand.h
@@ -36,17 +36,16 @@
#define _D_FILE_ALLOCATION_DISPATCHER_COMMAND_H_
#include "Command.h"
-#include "DownloadEngine.h"
+
+class DownloadEngine;
class FileAllocationDispatcherCommand : public Command {
private:
DownloadEngine* _e;
public:
- FileAllocationDispatcherCommand(int cuid, DownloadEngine* e):
- Command(cuid), _e(e)
- {
- setStatusRealtime();
- }
+ FileAllocationDispatcherCommand(int32_t cuid, DownloadEngine* e);
+
+ virtual ~FileAllocationDispatcherCommand();
virtual bool execute();
};
diff --git a/src/FileAllocationEntry.cc b/src/FileAllocationEntry.cc
index 77690475..af9c67c1 100644
--- a/src/FileAllocationEntry.cc
+++ b/src/FileAllocationEntry.cc
@@ -33,22 +33,35 @@
*/
/* copyright --> */
#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();
+}
diff --git a/src/FileAllocationEntry.h b/src/FileAllocationEntry.h
index 6108f41a..02843c03 100644
--- a/src/FileAllocationEntry.h
+++ b/src/FileAllocationEntry.h
@@ -37,32 +37,29 @@
#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:
- int64_t _offset;
+ FileAllocationIteratorHandle _fileAllocationIterator;
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();
+
+ virtual Commands prepareForNextAction(DownloadEngine* e) = 0;
};
typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;
diff --git a/src/FileAllocationIterator.h b/src/FileAllocationIterator.h
new file mode 100644
index 00000000..10685e76
--- /dev/null
+++ b/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_
diff --git a/src/TorrentConsoleDownloadEngine.cc b/src/FileAllocationMan.cc
index ad036147..205012ff 100644
--- a/src/TorrentConsoleDownloadEngine.cc
+++ b/src/FileAllocationMan.cc
@@ -32,40 +32,50 @@
* files in the program, then also delete it here.
*/
/* 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();
}
diff --git a/src/FileAllocationMan.h b/src/FileAllocationMan.h
index a4b2413e..17557d9b 100644
--- a/src/FileAllocationMan.h
+++ b/src/FileAllocationMan.h
@@ -36,57 +36,33 @@
#define _D_FILE_ALLOCATION_MAN_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 {
private:
FileAllocationEntries _fileAllocationEntries;
FileAllocationEntryHandle _currentFileAllocationEntry;
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;
diff --git a/src/FileEntry.cc b/src/FileEntry.cc
index d0c72de0..548f1123 100644
--- a/src/FileEntry.cc
+++ b/src/FileEntry.cc
@@ -45,7 +45,8 @@ FileEntry::FileEntry(const string& path,
FileEntry::~FileEntry() {}
-void FileEntry::setupDir(const string& parentDir) {
+void FileEntry::setupDir(const string& parentDir)
+{
string absPath = parentDir+"/"+path;
char* temp = strdup(absPath.c_str());
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());
}
}
+
+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;
+}
diff --git a/src/FileEntry.h b/src/FileEntry.h
index b395ce84..af475ab9 100644
--- a/src/FileEntry.h
+++ b/src/FileEntry.h
@@ -50,20 +50,10 @@ public:
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& operator=(const FileEntry& entry);
+
string getBasename() const
{
return File(path).getBasename();
diff --git a/src/FillRequestGroupCommand.cc b/src/FillRequestGroupCommand.cc
index 5c4b6399..85786af8 100644
--- a/src/FillRequestGroupCommand.cc
+++ b/src/FillRequestGroupCommand.cc
@@ -33,11 +33,33 @@
*/
/* copyright --> */
#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()
{
- _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;
}
_e->commands.push_back(this);
diff --git a/src/FillRequestGroupCommand.h b/src/FillRequestGroupCommand.h
index 68ffa9d2..bc2ff3b0 100644
--- a/src/FillRequestGroupCommand.h
+++ b/src/FillRequestGroupCommand.h
@@ -37,8 +37,11 @@
#include "Command.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 {
private:
@@ -47,13 +50,9 @@ private:
int32_t _interval;
Time _checkPoint;
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();
diff --git a/src/FtpConnection.cc b/src/FtpConnection.cc
index 39d8ef82..f87d37b7 100644
--- a/src/FtpConnection.cc
+++ b/src/FtpConnection.cc
@@ -34,8 +34,6 @@
/* copyright --> */
#include "FtpConnection.h"
#include "Util.h"
-#include "DlAbortEx.h"
-#include "DlRetryEx.h"
#include "message.h"
#include "prefs.h"
#include "LogFactory.h"
@@ -48,19 +46,25 @@ FtpConnection::FtpConnection(int32_t cuid, const SocketHandle& socket,
FtpConnection::~FtpConnection() {}
-void FtpConnection::sendUser() const {
+void FtpConnection::sendUser() const
+ throw(DlRetryEx*)
+{
string request = "USER "+req->resolveFtpAuthConfig()->getUser()+"\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
socket->writeData(request);
}
-void FtpConnection::sendPass() const {
+void FtpConnection::sendPass() const
+ throw(DlRetryEx*)
+{
string request = "PASS "+req->resolveFtpAuthConfig()->getPassword()+"\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, "PASS ********");
socket->writeData(request);
}
-void FtpConnection::sendType() const {
+void FtpConnection::sendType() const
+ throw(DlRetryEx*)
+{
string type;
if(option->get(PREF_FTP_TYPE) == V_ASCII) {
type = "A";
@@ -72,25 +76,33 @@ void FtpConnection::sendType() const {
socket->writeData(request);
}
-void FtpConnection::sendCwd() const {
- string request = "CWD "+req->getDir()+"\r\n";
+void FtpConnection::sendCwd() const
+ throw(DlRetryEx*)
+{
+ string request = "CWD "+Util::urldecode(req->getDir())+"\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
socket->writeData(request);
}
-void FtpConnection::sendSize() const {
- string request = "SIZE "+req->getFile()+"\r\n";
+void FtpConnection::sendSize() const
+ throw(DlRetryEx*)
+{
+ string request = "SIZE "+Util::urldecode(req->getFile())+"\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
socket->writeData(request);
}
-void FtpConnection::sendPasv() const {
+void FtpConnection::sendPasv() const
+ throw(DlRetryEx*)
+{
string request = "PASV\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
socket->writeData(request);
}
-SocketHandle FtpConnection::sendPort() const {
+SocketHandle FtpConnection::sendPort() const
+ throw(DlAbortEx*, DlRetryEx*)
+{
SocketHandle serverSocket;
serverSocket->beginListen();
@@ -109,19 +121,24 @@ SocketHandle FtpConnection::sendPort() const {
return serverSocket;
}
-void FtpConnection::sendRest(const SegmentHandle& segment) 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());
socket->writeData(request);
}
-void FtpConnection::sendRetr() const {
- string request = "RETR "+req->getFile()+"\r\n";
+void FtpConnection::sendRetr() const
+ throw(DlRetryEx*)
+{
+ string request = "RETR "+Util::urldecode(req->getFile())+"\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
socket->writeData(request);
}
-int32_t FtpConnection::getStatus(const string& response) const {
+int32_t FtpConnection::getStatus(const string& response) const
+{
int32_t status;
// When the response is not like "%d %*s",
// we return 0.
@@ -136,7 +153,8 @@ int32_t FtpConnection::getStatus(const string& response) const {
}
}
-bool FtpConnection::isEndOfResponse(int32_t status, const string& response) const {
+bool FtpConnection::isEndOfResponse(int32_t status, const string& response) const
+{
if(response.size() <= 4) {
return false;
}
@@ -156,7 +174,9 @@ bool FtpConnection::isEndOfResponse(int32_t status, const string& response) cons
}
}
-bool FtpConnection::bulkReceiveResponse(pair<int32_t, string>& response) {
+bool FtpConnection::bulkReceiveResponse(pair<int32_t, string>& response)
+ throw(DlRetryEx*)
+{
char buf[1024];
while(socket->isReadable(0)) {
int32_t size = sizeof(buf)-1;
@@ -188,7 +208,9 @@ bool FtpConnection::bulkReceiveResponse(pair<int32_t, string>& response) {
}
}
-int32_t FtpConnection::receiveResponse() {
+int32_t FtpConnection::receiveResponse()
+ throw(DlRetryEx*)
+{
pair<int32_t, string> response;
if(bulkReceiveResponse(response)) {
return response.first;
@@ -197,7 +219,9 @@ int32_t FtpConnection::receiveResponse() {
}
}
-int32_t FtpConnection::receiveSizeResponse(int64_t& size) {
+int32_t FtpConnection::receiveSizeResponse(int64_t& size)
+ throw(DlRetryEx*)
+{
pair<int32_t, string> response;
if(bulkReceiveResponse(response)) {
if(response.first == 213) {
@@ -209,7 +233,9 @@ int32_t FtpConnection::receiveSizeResponse(int64_t& size) {
}
}
-int32_t FtpConnection::receivePasvResponse(pair<string, int32_t>& dest) {
+int32_t FtpConnection::receivePasvResponse(pair<string, int32_t>& dest)
+ throw(DlRetryEx*)
+{
pair<int32_t, string> response;
if(bulkReceiveResponse(response)) {
if(response.first == 227) {
diff --git a/src/FtpConnection.h b/src/FtpConnection.h
index 766d3720..6d3a17dc 100644
--- a/src/FtpConnection.h
+++ b/src/FtpConnection.h
@@ -35,16 +35,16 @@
#ifndef _D_FTP_CONNECTION_H_
#define _D_FTP_CONNECTION_H_
+#include "common.h"
#include "Socket.h"
#include "Option.h"
#include "Logger.h"
#include "Segment.h"
#include "Request.h"
-#include "common.h"
+#include "DlAbortEx.h"
+#include "DlRetryEx.h"
#include <utility>
-using namespace std;
-
class FtpConnection {
private:
int32_t cuid;
@@ -57,24 +57,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);
+ bool bulkReceiveResponse(pair<int32_t, string>& response) throw(DlRetryEx*);
public:
FtpConnection(int32_t cuid, const SocketHandle& socket,
const RequestHandle req, const Option* op);
~FtpConnection();
- 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;
+ 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*);
- int32_t receiveResponse();
- int32_t receiveSizeResponse(int64_t& size);
- int32_t receivePasvResponse(pair<string, int32_t>& dest);
+ int32_t receiveResponse() throw(DlRetryEx*);
+ int32_t receiveSizeResponse(int64_t& size) throw(DlRetryEx*);
+ int32_t receivePasvResponse(pair<string, int32_t>& dest) throw(DlRetryEx*);
};
#endif // _D_FTP_CONNECTION_H_
diff --git a/src/FtpDownloadCommand.cc b/src/FtpDownloadCommand.cc
index e1c6ef8e..c2bb39a5 100644
--- a/src/FtpDownloadCommand.cc
+++ b/src/FtpDownloadCommand.cc
@@ -33,6 +33,7 @@
*/
/* copyright --> */
#include "FtpDownloadCommand.h"
+#include "Request.h"
FtpDownloadCommand::FtpDownloadCommand(int cuid,
const RequestHandle req,
diff --git a/src/FtpInitiateConnectionCommand.cc b/src/FtpInitiateConnectionCommand.cc
index 4837769e..466bff9b 100644
--- a/src/FtpInitiateConnectionCommand.cc
+++ b/src/FtpInitiateConnectionCommand.cc
@@ -33,6 +33,11 @@
*/
/* copyright --> */
#include "FtpInitiateConnectionCommand.h"
+#include "NameResolver.h"
+#include "DownloadEngine.h"
+#include "RequestGroup.h"
+#include "Option.h"
+#include "Request.h"
#include "FtpNegotiationCommand.h"
#include "HttpRequestCommand.h"
#include "FtpTunnelRequestCommand.h"
@@ -111,3 +116,10 @@ bool FtpInitiateConnectionCommand::useHttpProxyGet() const {
bool FtpInitiateConnectionCommand::useHttpProxyConnect() const {
return useHttpProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_TUNNEL;
}
+
+#ifdef ENABLE_ASYNC_DNS
+bool FtpInitiateConnectionCommand::nameResolveFinished() const {
+ return nameResolver->getStatus() == NameResolver::STATUS_SUCCESS ||
+ nameResolver->getStatus() == NameResolver::STATUS_ERROR;
+}
+#endif // ENABLE_ASYNC_DNS
diff --git a/src/FtpInitiateConnectionCommand.h b/src/FtpInitiateConnectionCommand.h
index acda5af0..9bcdd55a 100644
--- a/src/FtpInitiateConnectionCommand.h
+++ b/src/FtpInitiateConnectionCommand.h
@@ -44,10 +44,7 @@ private:
bool useHttpProxyGet() const;
bool useHttpProxyConnect() const;
#ifdef ENABLE_ASYNC_DNS
- virtual bool nameResolveFinished() const {
- return nameResolver->getStatus() == NameResolver::STATUS_SUCCESS ||
- nameResolver->getStatus() == NameResolver::STATUS_ERROR;
- }
+ virtual bool nameResolveFinished() const;
#endif // ENABLE_ASYNC_DNS
protected:
virtual bool executeInternal();
diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc
index 4b5c3008..fed6658a 100644
--- a/src/FtpNegotiationCommand.cc
+++ b/src/FtpNegotiationCommand.cc
@@ -33,13 +33,17 @@
*/
/* copyright --> */
#include "FtpNegotiationCommand.h"
+#include "DownloadEngine.h"
+#include "FtpConnection.h"
+#include "RequestGroup.h"
+#include "PieceStorage.h"
#include "FtpDownloadCommand.h"
#include "DlAbortEx.h"
#include "DlRetryEx.h"
#include "message.h"
#include "prefs.h"
#include "Util.h"
-#include "FatalException.h"
+#include "SingleFileDownloadContext.h"
FtpNegotiationCommand::FtpNegotiationCommand(int32_t cuid,
const RequestHandle& req,
@@ -189,28 +193,29 @@ bool FtpNegotiationCommand::recvSize() {
if(size == INT64_MAX || size < 0) {
throw new DlAbortEx(EX_TOO_LARGE_FILE, Util::llitos(size, true).c_str());
}
- if(!_requestGroup->getSegmentMan()->downloadStarted) {
- _requestGroup->getSegmentMan()->downloadStarted = true;
- _requestGroup->getSegmentMan()->totalSize = size;
- _requestGroup->getSegmentMan()->filename = Util::urldecode(req->getFile());
+ if(_requestGroup->getPieceStorage().isNull()) {
+ SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setTotalLength(size);
+ SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setFilename(Util::urldecode(req->getFile()));
+
+ initPieceStorage();
// TODO validate filename and totalsize against hintFilename and hintTotalSize if these are provided.
_requestGroup->validateTotalLengthByHint(size);
if(req->getMethod() == Request::METHOD_HEAD) {
- _requestGroup->getSegmentMan()->isSplittable = false; // TODO because we don't want segment file to be saved.
+ //_requestGroup->getSegmentMan()->isSplittable = false; // TODO because we don't want segment file to be saved.
sequence = SEQ_HEAD_OK;
return false;
}
if(e->option->get(PREF_CHECK_INTEGRITY) != V_TRUE) {
- if(_requestGroup->downloadFinishedByFileLength()) {
+ if(downloadFinishedByFileLength()) {
logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, cuid, _requestGroup->getFilePath().c_str());
sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED;
return false;
}
}
- _requestGroup->loadAndOpenFile();
- _requestGroup->prepareForNextAction(cuid, req, e);
+ loadAndOpenFile();
+ prepareForNextAction();
sequence = SEQ_FILE_PREPARATION;
e->noWait = true;
diff --git a/src/FtpNegotiationCommand.h b/src/FtpNegotiationCommand.h
index 6b9fc8c6..3f158983 100644
--- a/src/FtpNegotiationCommand.h
+++ b/src/FtpNegotiationCommand.h
@@ -36,7 +36,8 @@
#define _D_FTP_NEGOTIATION_COMMAND_H_
#include "AbstractCommand.h"
-#include "FtpConnection.h"
+
+class FtpConnection;
class FtpNegotiationCommand : public AbstractCommand {
private:
diff --git a/src/GrowSegment.cc b/src/GrowSegment.cc
new file mode 100644
index 00000000..b772fe80
--- /dev/null
+++ b/src/GrowSegment.cc
@@ -0,0 +1,54 @@
+/* <!-- 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 "GrowSegment.h"
+#include "Piece.h"
+
+GrowSegment::GrowSegment(const PieceHandle& piece):
+ _piece(piece), _writtenLength(0) {}
+
+GrowSegment::~GrowSegment() {}
+
+void GrowSegment::updateWrittenLength(int32_t bytes)
+{
+ _writtenLength += bytes;
+ _piece->reconfigure(_writtenLength);
+ _piece->setAllBlock();
+}
+
+PieceHandle GrowSegment::getPiece() const
+{
+ return _piece;
+}
+
diff --git a/src/GrowSegment.h b/src/GrowSegment.h
new file mode 100644
index 00000000..85f567ec
--- /dev/null
+++ b/src/GrowSegment.h
@@ -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 --> */
+#ifndef _D_GROW_SEGMENT_H_
+#define _D_GROW_SEGMENT_H_
+
+#include "Segment.h"
+
+class GrowSegment:public Segment {
+private:
+ PieceHandle _piece;
+ int32_t _writtenLength;
+public:
+ GrowSegment(const PieceHandle& piece);
+
+ virtual ~GrowSegment();
+
+ virtual bool complete() const
+ {
+ return false;
+ }
+
+ virtual int32_t getIndex() const
+ {
+ return 0;
+ }
+
+ virtual int64_t getPosition() const
+ {
+ return 0;
+ }
+
+ virtual int64_t getPositionToWrite() const
+ {
+ return _writtenLength;
+ }
+
+ virtual int32_t getLength() const
+ {
+ return 0;
+ }
+
+ virtual int32_t getSegmentLength() const
+ {
+ return 0;
+ }
+
+ virtual int32_t getWrittenLength() const
+ {
+ return _writtenLength;
+ }
+
+ virtual int32_t getOverflowLength() const
+ {
+ return 0;
+ }
+
+ virtual void updateWrittenLength(int32_t bytes);
+
+ virtual PieceHandle getPiece() const;
+};
+
+typedef SharedHandle<GrowSegment> GrowSegmentHandle;
+
+#endif // _D_GROW_SEGMENT_H_
+
diff --git a/src/HaveEraseCommand.cc b/src/HaveEraseCommand.cc
index ecb209c9..c901829f 100644
--- a/src/HaveEraseCommand.cc
+++ b/src/HaveEraseCommand.cc
@@ -33,23 +33,29 @@
*/
/* copyright --> */
#include "HaveEraseCommand.h"
+#include "DownloadEngine.h"
+#include "RequestGroupMan.h"
+#include "PieceStorage.h"
+#include "RequestGroup.h"
-HaveEraseCommand::HaveEraseCommand(int32_t cuid,
- TorrentDownloadEngine* e,
- const BtContextHandle& btContext,
- int32_t interval)
- :BtContextAwareCommand(cuid, btContext),
- e(e),
- interval(interval) {}
+HaveEraseCommand::HaveEraseCommand(int32_t cuid, DownloadEngine* e, int32_t interval)
+ :TimeBasedCommand(cuid, e, interval) {}
-bool HaveEraseCommand::execute() {
- if(btRuntime->isHalt()) {
- return true;
+HaveEraseCommand::~HaveEraseCommand() {}
+
+void HaveEraseCommand::preProcess()
+{
+ if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
+ _exit = true;
}
- if(cp.elapsed(interval)) {
- cp.reset();
- pieceStorage->removeAdvertisedPiece(5);
+}
+
+void HaveEraseCommand::process()
+{
+ for(int32_t i = 0; i < _e->_requestGroupMan->countRequestGroup(); ++i) {
+ PieceStorageHandle ps = _e->_requestGroupMan->getRequestGroup(i)->getPieceStorage();
+ if(!ps.isNull()) {
+ ps->removeAdvertisedPiece(5);
+ }
}
- e->commands.push_back(this);
- return false;
}
diff --git a/src/HaveEraseCommand.h b/src/HaveEraseCommand.h
index 4875df23..ff713583 100644
--- a/src/HaveEraseCommand.h
+++ b/src/HaveEraseCommand.h
@@ -35,23 +35,18 @@
#ifndef _D_HAVE_ERASE_COMMAND_H_
#define _D_HAVE_ERASE_COMMAND_H_
-#include "BtContextAwareCommand.h"
-#include "TorrentDownloadEngine.h"
+#include "TimeBasedCommand.h"
-class HaveEraseCommand : public BtContextAwareCommand {
-private:
- TorrentDownloadEngine* e;
- Time cp;
- int32_t interval;
+class HaveEraseCommand : public TimeBasedCommand
+{
public:
- HaveEraseCommand(int32_t cuid,
- TorrentDownloadEngine* e,
- const BtContextHandle& btContext,
- int32_t interval);
+ HaveEraseCommand(int32_t cuid, DownloadEngine* e, int32_t interval);
- virtual ~HaveEraseCommand() {}
+ virtual ~HaveEraseCommand();
- virtual bool execute();
+ virtual void preProcess();
+
+ virtual void process();
};
#endif // _D_HAVE_ERASE_COMMAND_H_
diff --git a/src/HttpConnection.cc b/src/HttpConnection.cc
index 6f0e2c67..74362823 100644
--- a/src/HttpConnection.cc
+++ b/src/HttpConnection.cc
@@ -33,10 +33,7 @@
*/
/* copyright --> */
#include "HttpConnection.h"
-#include "DlRetryEx.h"
-#include "DlAbortEx.h"
#include "Util.h"
-#include "Base64.h"
#include "message.h"
#include "prefs.h"
#include "LogFactory.h"
@@ -66,6 +63,7 @@ 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());
@@ -75,6 +73,7 @@ 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 +82,9 @@ void HttpConnection::sendProxyRequest(const HttpRequestHandle& httpRequest)
new HttpHeaderProcessor()));
}
-HttpResponseHandle HttpConnection::receiveResponse() {
+HttpResponseHandle HttpConnection::receiveResponse()
+ throw(DlAbortEx*, DlRetryEx*)
+{
if(outstandingHttpRequests.size() == 0) {
throw new DlAbortEx(EX_NO_HTTP_REQUEST_ENTRY_FOUND);
}
diff --git a/src/HttpConnection.h b/src/HttpConnection.h
index f007ccc9..de723838 100644
--- a/src/HttpConnection.h
+++ b/src/HttpConnection.h
@@ -44,6 +44,8 @@
#include "Logger.h"
#include "HttpResponse.h"
#include "HttpHeaderProcessor.h"
+#include "DlRetryEx.h"
+#include "DlAbortEx.h"
class HttpRequestEntry {
private:
@@ -93,12 +95,12 @@ public:
* HTTP proxy(GET method).
* @param segment indicates starting postion of the file for downloading
*/
- void sendRequest(const HttpRequestHandle& httpRequest);
+ void sendRequest(const HttpRequestHandle& httpRequest) throw(DlRetryEx*);
/**
* Sends Http proxy request using CONNECT method.
*/
- void sendProxyRequest(const HttpRequestHandle& httpRequest);
+ void sendProxyRequest(const HttpRequestHandle& httpRequest) throw(DlRetryEx*);
/**
* Receives HTTP response from the server and returns HttpResponseHandle
@@ -111,7 +113,7 @@ public:
*
* @return HttpResponse or 0 if whole response header is not received
*/
- HttpResponseHandle receiveResponse();
+ HttpResponseHandle receiveResponse() throw(DlAbortEx*, DlRetryEx*);
HttpRequestHandle getFirstHttpRequest() const
{
diff --git a/src/HttpDownloadCommand.cc b/src/HttpDownloadCommand.cc
index de4d6f27..0993b94c 100644
--- a/src/HttpDownloadCommand.cc
+++ b/src/HttpDownloadCommand.cc
@@ -33,6 +33,9 @@
*/
/* copyright --> */
#include "HttpDownloadCommand.h"
+#include "RequestGroup.h"
+#include "DownloadEngine.h"
+#include "Request.h"
#include "HttpRequestCommand.h"
#include "Util.h"
#include "message.h"
@@ -47,7 +50,7 @@ HttpDownloadCommand::HttpDownloadCommand(int cuid,
HttpDownloadCommand::~HttpDownloadCommand() {}
bool HttpDownloadCommand::prepareForNextSegment() {
- if(!_requestGroup->getSegmentMan()->finished()) {
+ if(!_requestGroup->downloadFinished()) {
if(req->isKeepAlive()) {
Command* command = new HttpRequestCommand(cuid, req, _requestGroup, e, socket);
e->commands.push_back(command);
diff --git a/src/HttpHeaderProcessor.cc b/src/HttpHeaderProcessor.cc
index 23e97411..51b83fad 100644
--- a/src/HttpHeaderProcessor.cc
+++ b/src/HttpHeaderProcessor.cc
@@ -34,23 +34,24 @@
/* copyright --> */
#include "HttpHeaderProcessor.h"
#include "message.h"
-#include "DlRetryEx.h"
-#include "DlAbortEx.h"
#include "Util.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) {
@@ -87,6 +88,7 @@ void HttpHeaderProcessor::clear()
}
pair<string, HttpHeaderHandle> HttpHeaderProcessor::getHttpStatusHeader()
+ throw(DlRetryEx*)
{
strm.seekg(0, ios::beg);
string line;
diff --git a/src/HttpHeaderProcessor.h b/src/HttpHeaderProcessor.h
index 51491602..59ffa4d8 100644
--- a/src/HttpHeaderProcessor.h
+++ b/src/HttpHeaderProcessor.h
@@ -37,6 +37,8 @@
#include "common.h"
#include "HttpHeader.h"
+#include "DlRetryEx.h"
+#include "DlAbortEx.h"
#include <utility>
#include <sstream>
@@ -45,16 +47,16 @@ private:
stringstream strm;
int32_t _limit;
- void checkHeaderLimit(int32_t incomingLength);
+ void checkHeaderLimit(int32_t incomingLength) throw(DlAbortEx*);
public:
HttpHeaderProcessor():_limit(4096) {}
~HttpHeaderProcessor() {}
- void update(const char* data, int32_t length);
+ void update(const char* data, int32_t length) throw(DlAbortEx*);
- void update(const string& data);
+ void update(const string& data) throw(DlAbortEx*);
/**
* Returns true if end of header is reached.
@@ -66,7 +68,7 @@ public:
*/
int32_t getPutBackDataLength() const;
- pair<string, HttpHeaderHandle> getHttpStatusHeader();
+ pair<string, HttpHeaderHandle> getHttpStatusHeader() throw(DlRetryEx*);
string getHeaderString() const;
diff --git a/src/HttpInitiateConnectionCommand.cc b/src/HttpInitiateConnectionCommand.cc
index 707ff73e..a3680eb2 100644
--- a/src/HttpInitiateConnectionCommand.cc
+++ b/src/HttpInitiateConnectionCommand.cc
@@ -33,6 +33,10 @@
*/
/* copyright --> */
#include "HttpInitiateConnectionCommand.h"
+#include "NameResolver.h"
+#include "DownloadEngine.h"
+#include "Option.h"
+#include "Request.h"
#include "HttpRequestCommand.h"
#include "HttpProxyRequestCommand.h"
#include "Util.h"
@@ -110,3 +114,10 @@ bool HttpInitiateConnectionCommand::useProxyGet() {
bool HttpInitiateConnectionCommand::useProxyTunnel() {
return e->option->get(PREF_HTTP_PROXY_METHOD) == V_TUNNEL;
}
+
+#ifdef ENABLE_ASYNC_DNS
+bool HttpInitiateConnectionCommand::nameResolveFinished() const {
+ return nameResolver->getStatus() == NameResolver::STATUS_SUCCESS ||
+ nameResolver->getStatus() == NameResolver::STATUS_ERROR;
+}
+#endif // ENABLE_ASYNC_DNS
diff --git a/src/HttpInitiateConnectionCommand.h b/src/HttpInitiateConnectionCommand.h
index b77ede4e..fa0fa596 100644
--- a/src/HttpInitiateConnectionCommand.h
+++ b/src/HttpInitiateConnectionCommand.h
@@ -54,10 +54,7 @@ protected:
*/
virtual bool executeInternal();
#ifdef ENABLE_ASYNC_DNS
- virtual bool nameResolveFinished() const {
- return nameResolver->getStatus() == NameResolver::STATUS_SUCCESS ||
- nameResolver->getStatus() == NameResolver::STATUS_ERROR;
- }
+ virtual bool nameResolveFinished() const;
#endif // ENABLE_ASYNC_DNS
public:
HttpInitiateConnectionCommand(int cuid, const RequestHandle& req, RequestGroup* requestGroup, DownloadEngine* e);
diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc
index 603523d8..942f6947 100644
--- a/src/HttpRequest.cc
+++ b/src/HttpRequest.cc
@@ -40,7 +40,7 @@
RangeHandle HttpRequest::getRange() const
{
// content-length is always 0
- if(segment->isNull()) {
+ if(segment.isNull()) {
return new Range(0, 0, 0);
} else {
return new Range(getStartByte(), getEndByte(), entityLength);
@@ -49,7 +49,7 @@ RangeHandle HttpRequest::getRange() const
bool HttpRequest::isRangeSatisfied(const RangeHandle& range) const
{
- if(segment->isNull()) {
+ if(segment.isNull()) {
return true;
}
if(getStartByte() == range->getStartByte() &&
@@ -83,7 +83,7 @@ string HttpRequest::createRequest() const
}
requestLine +=
string(" HTTP/1.1\r\n")+
- "User-Agent: "+Util::urlencode(userAgent)+"\r\n"+
+ "User-Agent: "+userAgent+"\r\n"+
"Accept: */*\r\n"+ /* */
"Host: "+getHostText(getHost(), getPort())+"\r\n"+
"Pragma: no-cache\r\n"+
@@ -91,7 +91,8 @@ string HttpRequest::createRequest() const
if(!request->isKeepAlive()) {
requestLine += "Connection: close\r\n";
}
- if(segment->length > 0) {
+ if(!segment.isNull() && segment->getLength() > 0 &&
+ (request->isKeepAlive() || getStartByte() > 0)) {
requestLine += "Range: bytes="+Util::llitos(getStartByte());
requestLine += "-";
if(request->isKeepAlive()) {
@@ -112,7 +113,6 @@ string HttpRequest::createRequest() const
if(getPreviousURI().size()) {
requestLine += "Referer: "+getPreviousURI()+"\r\n";
}
-
string cookiesValue;
Cookies cookies = request->cookieBox->criteriaFind(getHost(),
getDir(),
diff --git a/src/HttpRequest.h b/src/HttpRequest.h
index b943d2ea..488bacd3 100644
--- a/src/HttpRequest.h
+++ b/src/HttpRequest.h
@@ -168,7 +168,7 @@ public:
return 0;
} else {
if(request->isKeepAlive()) {
- return segment->getPosition()+segment->length-1;
+ return segment->getPosition()+segment->getLength()-1;
} else {
return 0;
}
diff --git a/src/HttpRequestCommand.cc b/src/HttpRequestCommand.cc
index b708dfd0..b5559715 100644
--- a/src/HttpRequestCommand.cc
+++ b/src/HttpRequestCommand.cc
@@ -33,6 +33,8 @@
*/
/* copyright --> */
#include "HttpRequestCommand.h"
+#include "DownloadEngine.h"
+#include "RequestGroup.h"
#include "HttpResponseCommand.h"
#include "HttpConnection.h"
#include "prefs.h"
@@ -61,7 +63,7 @@ bool HttpRequestCommand::executeInternal() {
httpRequest->setUserAgent(e->option->get(PREF_USER_AGENT));
httpRequest->setRequest(req);
httpRequest->setSegment(segment);
- httpRequest->setEntityLength(_requestGroup->getSegmentMan()->totalSize);
+ httpRequest->setEntityLength(_requestGroup->getTotalLength());
httpRequest->configure(e->option);
HttpConnectionHandle httpConnection = new HttpConnection(cuid, socket, e->option);
diff --git a/src/HttpResponse.cc b/src/HttpResponse.cc
index 3a75da50..6badc86e 100644
--- a/src/HttpResponse.cc
+++ b/src/HttpResponse.cc
@@ -33,13 +33,12 @@
*/
/* copyright --> */
#include "HttpResponse.h"
-#include "DlAbortEx.h"
-#include "DlRetryEx.h"
#include "ChunkedEncoding.h"
#include "Util.h"
#include "message.h"
void HttpResponse::validateResponse() const
+ throw(DlAbortEx*, DlRetryEx*)
{
if(status == 401) {
throw new DlAbortEx(EX_AUTH_FAILED);
diff --git a/src/HttpResponse.h b/src/HttpResponse.h
index ac7afc9f..09a38b09 100644
--- a/src/HttpResponse.h
+++ b/src/HttpResponse.h
@@ -40,6 +40,8 @@
#include "HttpHeader.h"
#include "TransferEncoding.h"
#include "LogFactory.h"
+#include "DlAbortEx.h"
+#include "DlRetryEx.h"
class HttpResponse {
private:
@@ -58,7 +60,7 @@ public:
~HttpResponse() {}
- void validateResponse() const;
+ void validateResponse() const throw(DlAbortEx*, DlRetryEx*);
/**
* Returns filename.
diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc
index 8a29619a..95dae918 100644
--- a/src/HttpResponseCommand.cc
+++ b/src/HttpResponseCommand.cc
@@ -33,6 +33,10 @@
*/
/* copyright --> */
#include "HttpResponseCommand.h"
+#include "DownloadEngine.h"
+#include "HttpResponse.h"
+#include "HttpConnection.h"
+#include "SegmentMan.h"
#include "DlAbortEx.h"
#include "DlRetryEx.h"
#include "HttpDownloadCommand.h"
@@ -41,7 +45,9 @@
#include "prefs.h"
#include "File.h"
#include "InitiateConnectionCommandFactory.h"
-#include "FatalException.h"
+#include "SingleFileDownloadContext.h"
+#include "DiskAdaptor.h"
+#include "PieceStorage.h"
#include <sys/types.h>
#include <unistd.h>
@@ -59,10 +65,6 @@ HttpResponseCommand::~HttpResponseCommand() {}
bool HttpResponseCommand::executeInternal()
{
HttpRequestHandle httpRequest = httpConnection->getFirstHttpRequest();
- if(!(httpRequest->getSegment() == segment)) {
- logger->info(MSG_SEGMENT_CHANGED, cuid);
- return prepareForRetry(0);
- }
HttpResponseHandle httpResponse = httpConnection->receiveResponse();
if(httpResponse.isNull()) {
// The server has not responded to our request yet.
@@ -87,7 +89,7 @@ bool HttpResponseCommand::executeInternal()
e->noWait = true;
return prepareForRetry(0);
}
- if(_requestGroup->getSegmentMan()->downloadStarted) {
+ if(!_requestGroup->getPieceStorage().isNull()) {
// validate totalsize
_requestGroup->validateFilename(httpResponse->determinFilename());
_requestGroup->validateTotalLength(httpResponse->getEntityLength());
@@ -99,7 +101,7 @@ bool HttpResponseCommand::executeInternal()
_requestGroup->validateFilenameByHint(httpResponse->determinFilename());
_requestGroup->validateTotalLengthByHint(httpResponse->getEntityLength());
- _requestGroup->getSegmentMan()->filename = httpResponse->determinFilename();
+ SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setFilename(httpResponse->determinFilename());
if(httpResponse->isTransferEncodingSpecified()) {
return handleOtherEncoding(httpResponse);
} else {
@@ -111,27 +113,26 @@ bool HttpResponseCommand::executeInternal()
bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpResponse)
{
HttpRequestHandle httpRequest = httpResponse->getHttpRequest();
- // TODO quick and dirty way
- if(_requestGroup->isTorrent) {
- return doTorrentStuff(httpResponse);
- }
int64_t size = httpResponse->getEntityLength();
if(size == INT64_MAX || size < 0) {
throw new DlAbortEx(EX_TOO_LARGE_FILE, Util::llitos(size, true).c_str());
}
- _requestGroup->getSegmentMan()->isSplittable = !(size == 0);
- _requestGroup->getSegmentMan()->downloadStarted = true;
- _requestGroup->getSegmentMan()->totalSize = size;
-
+ //_requestGroup->getSegmentMan()->isSplittable = !(size == 0);
+ //_requestGroup->getSegmentMan()->totalSize = size;
+ //_requestGroup->getSegmentMan()->initDownloadContext(size);
+
+ SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setTotalLength(size);
+ initPieceStorage();
+
// quick hack for method 'head'
if(httpRequest->getMethod() == Request::METHOD_HEAD) {
// TODO because we don't want segment file to be saved.
- _requestGroup->getSegmentMan()->isSplittable = false;
+ //_requestGroup->getSegmentMan()->isSplittable = false;
return true;
}
if(e->option->get(PREF_CHECK_INTEGRITY) != V_TRUE) {
- if(_requestGroup->downloadFinishedByFileLength()) {
+ if(downloadFinishedByFileLength()) {
logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, cuid, _requestGroup->getFilePath().c_str());
return true;
}
@@ -143,8 +144,8 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpRe
if(_requestGroup->getRemainingUris().empty() && !file.exists()) {
command = createHttpDownloadCommand(httpResponse);
}
- _requestGroup->loadAndOpenFile();
- _requestGroup->prepareForNextAction(cuid, req, e, command);
+ loadAndOpenFile();
+ prepareForNextAction(command);
e->noWait = true;
} catch(Exception* e) {
delete command;
@@ -156,18 +157,22 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpRe
bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResponse) {
HttpRequestHandle httpRequest = httpResponse->getHttpRequest();
// we ignore content-length when transfer-encoding is set
- _requestGroup->getSegmentMan()->downloadStarted = true;
- _requestGroup->getSegmentMan()->isSplittable = false;
- _requestGroup->getSegmentMan()->totalSize = 0;
+ //_requestGroup->getSegmentMan()->isSplittable = false;
+ //_requestGroup->getSegmentMan()->totalSize = 0;
// quick hack for method 'head'
if(httpRequest->getMethod() == Request::METHOD_HEAD) {
return true;
}
// disable keep-alive
req->setKeepAlive(false);
- segment = _requestGroup->getSegmentMan()->getSegment(cuid);
- _requestGroup->shouldCancelDownloadForSafety();
- _requestGroup->getSegmentMan()->diskWriter->initAndOpenFile(_requestGroup->getSegmentMan()->getFilePath());
+
+ initPieceStorage();
+
+ //segment = _requestGroup->getSegmentMan()->getSegment(cuid);
+
+ shouldCancelDownloadForSafety();
+ // TODO handle file-size unknown case
+ _requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();//_requestGroup->getFilePath());
e->commands.push_back(createHttpDownloadCommand(httpResponse));
return true;
}
@@ -192,20 +197,3 @@ HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand(const HttpRe
return command;
}
-
-bool HttpResponseCommand::doTorrentStuff(const HttpResponseHandle& httpResponse)
-{
- int64_t size = httpResponse->getEntityLength();
- _requestGroup->getSegmentMan()->totalSize = size;
- if(size > 0) {
- _requestGroup->getSegmentMan()->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE),
- _requestGroup->getSegmentMan()->totalSize);
- }
- // disable keep-alive
- httpResponse->getHttpRequest()->getRequest()->setKeepAlive(false);
- _requestGroup->getSegmentMan()->isSplittable = false;
- _requestGroup->getSegmentMan()->downloadStarted = true;
- _requestGroup->getSegmentMan()->diskWriter->initAndOpenFile("/tmp/aria2"+Util::itos((int32_t)getpid()));
- e->commands.push_back(createHttpDownloadCommand(httpResponse));
- return true;
-}
diff --git a/src/HttpResponseCommand.h b/src/HttpResponseCommand.h
index f2c77061..18c3102e 100644
--- a/src/HttpResponseCommand.h
+++ b/src/HttpResponseCommand.h
@@ -36,8 +36,12 @@
#define _D_HTTP_RESPONSE_COMMAND_H_
#include "AbstractCommand.h"
-#include "HttpConnection.h"
-#include "HttpDownloadCommand.h"
+
+class HttpConnection;
+extern typedef SharedHandle<HttpConnection> HttpConnectionHandle;
+class HttpDownloadCommand;
+class HttpResponse;
+extern typedef SharedHandle<HttpResponse> HttpResponseHandle;
class HttpResponseCommand : public AbstractCommand {
private:
@@ -46,7 +50,6 @@ private:
bool handleDefaultEncoding(const HttpResponseHandle& httpResponse);
bool handleOtherEncoding(const HttpResponseHandle& httpResponse);
HttpDownloadCommand* createHttpDownloadCommand(const HttpResponseHandle& httpResponse);
- bool doTorrentStuff(const HttpResponseHandle& httpResponse);
protected:
bool executeInternal();
public:
diff --git a/src/IteratableChecksumValidator.cc b/src/IteratableChecksumValidator.cc
index 545d4328..d99acb16 100644
--- a/src/IteratableChecksumValidator.cc
+++ b/src/IteratableChecksumValidator.cc
@@ -42,7 +42,7 @@ void IteratableChecksumValidator::validateChunk()
{
if(!finished()) {
- char data[BUFSIZE];
+ unsigned char data[BUFSIZE];
int32_t size = _diskWriter->readData(data, sizeof(data), _currentOffset);
diff --git a/src/IteratableChunkChecksumValidator.cc b/src/IteratableChunkChecksumValidator.cc
index 0e43acc3..02d3a4ce 100644
--- a/src/IteratableChunkChecksumValidator.cc
+++ b/src/IteratableChunkChecksumValidator.cc
@@ -36,47 +36,57 @@
#include "Util.h"
#include "message.h"
#include "MessageDigestHelper.h"
+#include "DiskAdaptor.h"
void IteratableChunkChecksumValidator::validateChunk()
{
if(!finished()) {
- string actualChecksum = calculateActualChecksum();
-
-
- if(!_chunkChecksum->validateChunk(actualChecksum, _currentIndex)) {
- int64_t offset = ((int64_t)_currentIndex)*_chunkChecksum->getChecksumLength();
- // wrong checksum
- logger->info(EX_INVALID_CHUNK_CHECKSUM,
- _currentIndex,
- Util::llitos(offset, true).c_str(),
- _chunkChecksum->getChecksum(_currentIndex).c_str(),
- actualChecksum.c_str());
- int32_t startIndex;
- int32_t endIndex;
- Util::indexRange(startIndex, endIndex, offset,
- _chunkChecksum->getChecksumLength(),
- _bitfield->getBlockLength());
- _bitfield->unsetBitRange(startIndex, endIndex);
+ string actualChecksum;
+ try {
+ actualChecksum = calculateActualChecksum();
+ } catch(DlAbortEx* 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);
+ _currentIndex++;
+ return;
}
- _currentIndex++;
+ if(actualChecksum == _dctx->getPieceHashes()[_currentIndex]) {
+ _bitfield->setBit(_currentIndex);
+ } else {
+ _logger->info(EX_INVALID_CHUNK_CHECKSUM,
+ _currentIndex,
+ Util::llitos(getCurrentOffset(), true).c_str(),
+ _dctx->getPieceHashes()[_currentIndex].c_str(),
+ actualChecksum.c_str());
+ _bitfield->unsetBit(_currentIndex);
+ }
+ _currentIndex++;
}
}
string IteratableChunkChecksumValidator::calculateActualChecksum()
{
- int64_t offset = ((int64_t)_currentIndex)*_chunkChecksum->getChecksumLength();
- int32_t length = _diskWriter->size() < offset+_chunkChecksum->getChecksumLength() ? _diskWriter->size()-offset : _chunkChecksum->getChecksumLength();
- return MessageDigestHelper::digest(_chunkChecksum->getAlgo(), _diskWriter, offset, length);
+ int64_t offset = getCurrentOffset();
+ int32_t length;
+ // When validating last piece
+ if(_currentIndex+1 == (uint32_t)_dctx->getNumPieces()) {
+ length = _dctx->getTotalLength()-offset;
+ } else {
+ length = _dctx->getPieceLength();
+ }
+ return MessageDigestHelper::digest(_dctx->getPieceHashAlgo(),
+ _pieceStorage->getDiskAdaptor(),
+ offset, length);
}
-bool IteratableChunkChecksumValidator::canValidate() const
+void IteratableChunkChecksumValidator::init()
{
- // We assume file is already opened using DiskWriter::open or openExistingFile.
- return _chunkChecksum->getEstimatedDataLength() >= _diskWriter->size();
+ _bitfield->clearAllBit();
+ _currentIndex = 0;
}
-void IteratableChunkChecksumValidator::init()
+void IteratableChunkChecksumValidator::updatePieceStorage()
{
- _bitfield->setAllBit();
- _currentIndex = 0;
+ _pieceStorage->setBitfield(_bitfield->getBitfield(), _bitfield->getBitfieldLength());
}
diff --git a/src/IteratableChunkChecksumValidator.h b/src/IteratableChunkChecksumValidator.h
index 6e4bb4bc..75c2b2e1 100644
--- a/src/IteratableChunkChecksumValidator.h
+++ b/src/IteratableChunkChecksumValidator.h
@@ -36,25 +36,29 @@
#define _D_ITERATABLE_CHUNK_CHECKSUM_VALIDATOR_H_
#include "common.h"
+#include "DownloadContext.h"
+#include "PieceStorage.h"
#include "BitfieldMan.h"
-#include "ChunkChecksum.h"
-#include "DiskWriter.h"
#include "LogFactory.h"
class IteratableChunkChecksumValidator
{
private:
- DiskWriterHandle _diskWriter;
+ DownloadContextHandle _dctx;
+ PieceStorageHandle _pieceStorage;
BitfieldMan* _bitfield;
- int32_t _currentIndex;
- ChunkChecksumHandle _chunkChecksum;
- const Logger* logger;
+ uint32_t _currentIndex;
+ const Logger* _logger;
string calculateActualChecksum();
public:
- IteratableChunkChecksumValidator():_diskWriter(0), _bitfield(0), _currentIndex(0), _chunkChecksum(0), logger(LogFactory::getInstance()) {}
-
- bool canValidate() const;
+ IteratableChunkChecksumValidator(const DownloadContextHandle& dctx,
+ const PieceStorageHandle& pieceStorage):
+ _dctx(dctx),
+ _pieceStorage(pieceStorage),
+ _bitfield(new BitfieldMan(_dctx->getPieceLength(), _dctx->getTotalLength())),
+ _currentIndex(0),
+ _logger(LogFactory::getInstance()) {}
void init();
@@ -62,38 +66,20 @@ public:
bool finished() const
{
- return _currentIndex >= _chunkChecksum->countChecksum();
- }
-
- void setDiskWriter(const DiskWriterHandle& diskWriter)
- {
- _diskWriter = diskWriter;
- }
-
- void setBitfield(BitfieldMan* bitfield)
- {
- _bitfield = bitfield;
- }
-
- void setChunkChecksum(const ChunkChecksumHandle& chunkChecksum)
- {
- _chunkChecksum = chunkChecksum;
+ return _currentIndex >= (uint32_t)_dctx->getNumPieces();
}
int64_t getCurrentOffset() const
{
- return ((int64_t)_currentIndex)*_chunkChecksum->getChecksumLength();
+ return ((int64_t)_currentIndex)*_dctx->getPieceLength();
}
int64_t getTotalLength() const
{
- return _bitfield->getTotalLength();
+ return _dctx->getTotalLength();
}
- ChunkChecksumHandle getChunkChecksum()
- {
- return _chunkChecksum;
- }
+ void updatePieceStorage();
};
typedef SharedHandle<IteratableChunkChecksumValidator> IteratableChunkChecksumValidatorHandle;
diff --git a/src/Makefile.am b/src/Makefile.am
index 39441014..58c7446f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,7 @@
bin_PROGRAMS = aria2c
-aria2c_SOURCES = main.cc
+aria2c_SOURCES = main.cc\
+ option_processing.cc\
+ version_usage.cc
SRCS = Socket.h\
SocketCore.cc SocketCore.h\
Command.cc Command.h\
@@ -22,8 +24,9 @@ SRCS = Socket.h\
FtpTunnelResponseCommand.cc FtpTunnelResponseCommand.h\
SleepCommand.cc SleepCommand.h\
DownloadEngine.cc DownloadEngine.h\
- ConsoleDownloadEngine.cc ConsoleDownloadEngine.h\
- Segment.cc Segment.h\
+ Segment.h\
+ GrowSegment.cc GrowSegment.h\
+ PiecedSegment.cc PiecedSegment.h\
SegmentMan.cc SegmentMan.h\
Util.cc Util.h\
Request.cc Request.h\
@@ -60,8 +63,6 @@ SRCS = Socket.h\
Randomizer.h\
SimpleRandomizer.cc SimpleRandomizer.h\
FileAllocator.h\
- FileAllocationMonitor.cc FileAllocationMonitor.h\
- ConsoleFileAllocationMonitor.cc ConsoleFileAllocationMonitor.h\
HttpResponse.cc HttpResponse.h\
HttpRequest.cc HttpRequest.h\
Range.h\
@@ -74,17 +75,18 @@ SRCS = Socket.h\
DefaultAuthResolver.cc DefaultAuthResolver.h\
NetrcAuthResolver.cc NetrcAuthResolver.h\
RequestFactory.cc RequestFactory.h\
- DefaultFileAllocator.cc DefaultFileAllocator.h\
- GlowFileAllocator.cc GlowFileAllocator.h\
OptionParser.cc OptionParser.h\
OptionHandlerFactory.cc OptionHandlerFactory.h\
NameResolver.cc NameResolver.h\
RequestGroup.cc RequestGroup.h\
+ RequestGroupAware.cc RequestGroupAware.h\
RequestGroupMan.cc RequestGroupMan.h\
+ FileAllocationMan.cc FileAllocationMan.h\
FileAllocationCommand.cc FileAllocationCommand.h\
FillRequestGroupCommand.cc FillRequestGroupCommand.h\
FileAllocationDispatcherCommand.cc FileAllocationDispatcherCommand.h\
FileAllocationEntry.cc FileAllocationEntry.h\
+ StreamFileAllocationEntry.cc StreamFileAllocationEntry.h\
MultiUrlRequestInfo.cc MultiUrlRequestInfo.h\
UriListParser.cc UriListParser.h\
SegmentManFactory.h\
@@ -110,17 +112,30 @@ SRCS = Socket.h\
NumberDecorator.h\
AlphaNumberDecorator.h\
TimeBasedCommand.cc TimeBasedCommand.h\
- AutoSaveCommand.cc AutoSaveCommand.h
+ AutoSaveCommand.cc AutoSaveCommand.h\
+ UnknownLengthPieceStorage.cc UnknownLengthPieceStorage.h\
+ StatCalc.h\
+ ConsoleStatCalc.cc ConsoleStatCalc.h\
+ TransferStat.cc TransferStat.h\
+ Dependency.h\
+ BtProgressInfoFile.h\
+ DefaultBtProgressInfoFile.cc DefaultBtProgressInfoFile.h\
+ NullProgressInfoFile.h\
+ FileAllocationIterator.h\
+ SingleFileAllocationIterator.cc SingleFileAllocationIterator.h\
+ PostDownloadHandler.cc PostDownloadHandler.h\
+ HaveEraseCommand.cc HaveEraseCommand.h\
+ Piece.cc Piece.h
# debug_new.cpp
if ENABLE_MESSAGE_DIGEST
-SRCS += ChunkChecksumValidator.cc ChunkChecksumValidator.h\
- IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\
+SRCS += IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\
IteratableChecksumValidator.cc IteratableChecksumValidator.h\
ChecksumCommand.cc ChecksumCommand.h\
CheckIntegrityCommand.cc CheckIntegrityCommand.h\
CheckIntegrityEntry.cc CheckIntegrityEntry.h\
- CheckIntegrityMan.h\
+ StreamCheckIntegrityEntry.cc StreamCheckIntegrityEntry.h\
+ CheckIntegrityMan.cc CheckIntegrityMan.h\
messageDigest.cc messageDigest.h\
MessageDigestHelper.cc MessageDigestHelper.h
endif # ENABLE_MESSAGE_DIGEST
@@ -139,12 +154,8 @@ SRCS += MetaEntry.h\
PeerInitiateConnectionCommand.cc PeerInitiateConnectionCommand.h\
PeerInteractionCommand.cc PeerInteractionCommand.h\
Peer.cc Peer.h\
- TorrentDownloadEngine.cc TorrentDownloadEngine.h\
- TorrentConsoleDownloadEngine.cc TorrentConsoleDownloadEngine.h\
PeerListenCommand.cc PeerListenCommand.h\
- Piece.cc Piece.h\
RequestSlot.cc RequestSlot.h\
- TorrentAutoSaveCommand.cc TorrentAutoSaveCommand.h\
Directory.cc Directory.h\
TrackerWatcherCommand.cc TrackerWatcherCommand.h\
DiskAdaptor.cc DiskAdaptor.h\
@@ -152,11 +163,8 @@ SRCS += MetaEntry.h\
CopyDiskAdaptor.cc CopyDiskAdaptor.h\
DirectDiskAdaptor.cc DirectDiskAdaptor.h\
MultiDiskAdaptor.cc MultiDiskAdaptor.h\
- TrackerUpdateCommand.cc TrackerUpdateCommand.h\
ByteArrayDiskWriter.cc ByteArrayDiskWriter.h\
PeerChokeCommand.cc PeerChokeCommand.h\
- HaveEraseCommand.cc HaveEraseCommand.h\
- TorrentRequestInfo.cc TorrentRequestInfo.h\
SeedCriteria.h\
TimeSeedCriteria.h\
ShareRatioSeedCriteria.h\
@@ -177,8 +185,6 @@ SRCS += MetaEntry.h\
DefaultBtAnnounce.cc DefaultBtAnnounce.h\
BtRegistry.cc BtRegistry.h\
BtRuntime.h\
- BtProgressInfoFile.h\
- DefaultBtProgressInfoFile.cc DefaultBtProgressInfoFile.h\
BtContextAwareCommand.cc BtContextAwareCommand.h\
BtMessage.h\
AbstractBtMessage.h\
@@ -228,7 +234,13 @@ SRCS += MetaEntry.h\
DefaultBtInteractive.cc DefaultBtInteractive.h\
PeerObject.h\
ActivePeerConnectionCommand.cc ActivePeerConnectionCommand.h\
- TrackerSegmentManFactory.cc TrackerSegmentManFactory.h
+ BtDependency.cc BtDependency.h\
+ PeerReceiveHandshakeCommand.cc PeerReceiveHandshakeCommand.h\
+ BtSetup.cc BtSetup.h\
+ BtFileAllocationEntry.cc BtFileAllocationEntry.h\
+ BtPostDownloadHandler.cc BtPostDownloadHandler.h\
+ MultiFileAllocationIterator.cc MultiFileAllocationIterator.h\
+ BtCheckIntegrityEntry.cc BtCheckIntegrityEntry.h
endif # ENABLE_BITTORRENT
if ENABLE_METALINK
@@ -237,7 +249,8 @@ SRCS += Metalinker.cc Metalinker.h\
MetalinkResource.cc MetalinkResource.h\
MetalinkProcessor.h\
Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h\
- MetalinkRequestInfo.cc MetalinkRequestInfo.h
+ Metalink2RequestGroup.cc Metalink2RequestGroup.h\
+ MetalinkPostDownloadHandler.cc MetalinkPostDownloadHandler.h
endif # ENABLE_METALINK
if !HAVE_BASENAME
@@ -280,10 +293,10 @@ noinst_LIBRARIES = libaria2c.a
libaria2c_a_SOURCES = $(SRCS)
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
@LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@ @LIBARES_LIBS@\
- @LIBCARES_LIBS@ @WINSOCK_LIBS@ # -lprofiler
-#aria2c_LDFLAGS = #-pg
+ @LIBCARES_LIBS@ @WINSOCK_LIBS@ #-lprofiler
+#aria2c_LDFLAGS = -pg
AM_CPPFLAGS = -Wall\
-I../lib -I../intl -I$(top_srcdir)/intl\
@LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\
@LIBARES_CPPFLAGS@ @LIBCARES_CPPFLAGS@\
- -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ # -pg \ No newline at end of file
+ -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ #-pg \ No newline at end of file
diff --git a/src/Makefile.in b/src/Makefile.in
index 92fbf514..30ecdfa9 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -40,13 +40,13 @@ host_triplet = @host@
target_triplet = @target@
bin_PROGRAMS = aria2c$(EXEEXT)
# debug_new.cpp
-@ENABLE_MESSAGE_DIGEST_TRUE@am__append_1 = ChunkChecksumValidator.cc ChunkChecksumValidator.h\
-@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\
+@ENABLE_MESSAGE_DIGEST_TRUE@am__append_1 = IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\
@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidator.cc IteratableChecksumValidator.h\
@ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCommand.cc ChecksumCommand.h\
@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.cc CheckIntegrityCommand.h\
@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityEntry.cc CheckIntegrityEntry.h\
-@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityMan.h\
+@ENABLE_MESSAGE_DIGEST_TRUE@ StreamCheckIntegrityEntry.cc StreamCheckIntegrityEntry.h\
+@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityMan.cc CheckIntegrityMan.h\
@ENABLE_MESSAGE_DIGEST_TRUE@ messageDigest.cc messageDigest.h\
@ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelper.cc MessageDigestHelper.h
@@ -63,12 +63,8 @@ bin_PROGRAMS = aria2c$(EXEEXT)
@ENABLE_BITTORRENT_TRUE@ PeerInitiateConnectionCommand.cc PeerInitiateConnectionCommand.h\
@ENABLE_BITTORRENT_TRUE@ PeerInteractionCommand.cc PeerInteractionCommand.h\
@ENABLE_BITTORRENT_TRUE@ Peer.cc Peer.h\
-@ENABLE_BITTORRENT_TRUE@ TorrentDownloadEngine.cc TorrentDownloadEngine.h\
-@ENABLE_BITTORRENT_TRUE@ TorrentConsoleDownloadEngine.cc TorrentConsoleDownloadEngine.h\
@ENABLE_BITTORRENT_TRUE@ PeerListenCommand.cc PeerListenCommand.h\
-@ENABLE_BITTORRENT_TRUE@ Piece.cc Piece.h\
@ENABLE_BITTORRENT_TRUE@ RequestSlot.cc RequestSlot.h\
-@ENABLE_BITTORRENT_TRUE@ TorrentAutoSaveCommand.cc TorrentAutoSaveCommand.h\
@ENABLE_BITTORRENT_TRUE@ Directory.cc Directory.h\
@ENABLE_BITTORRENT_TRUE@ TrackerWatcherCommand.cc TrackerWatcherCommand.h\
@ENABLE_BITTORRENT_TRUE@ DiskAdaptor.cc DiskAdaptor.h\
@@ -76,11 +72,8 @@ bin_PROGRAMS = aria2c$(EXEEXT)
@ENABLE_BITTORRENT_TRUE@ CopyDiskAdaptor.cc CopyDiskAdaptor.h\
@ENABLE_BITTORRENT_TRUE@ DirectDiskAdaptor.cc DirectDiskAdaptor.h\
@ENABLE_BITTORRENT_TRUE@ MultiDiskAdaptor.cc MultiDiskAdaptor.h\
-@ENABLE_BITTORRENT_TRUE@ TrackerUpdateCommand.cc TrackerUpdateCommand.h\
@ENABLE_BITTORRENT_TRUE@ ByteArrayDiskWriter.cc ByteArrayDiskWriter.h\
@ENABLE_BITTORRENT_TRUE@ PeerChokeCommand.cc PeerChokeCommand.h\
-@ENABLE_BITTORRENT_TRUE@ HaveEraseCommand.cc HaveEraseCommand.h\
-@ENABLE_BITTORRENT_TRUE@ TorrentRequestInfo.cc TorrentRequestInfo.h\
@ENABLE_BITTORRENT_TRUE@ SeedCriteria.h\
@ENABLE_BITTORRENT_TRUE@ TimeSeedCriteria.h\
@ENABLE_BITTORRENT_TRUE@ ShareRatioSeedCriteria.h\
@@ -101,8 +94,6 @@ bin_PROGRAMS = aria2c$(EXEEXT)
@ENABLE_BITTORRENT_TRUE@ DefaultBtAnnounce.cc DefaultBtAnnounce.h\
@ENABLE_BITTORRENT_TRUE@ BtRegistry.cc BtRegistry.h\
@ENABLE_BITTORRENT_TRUE@ BtRuntime.h\
-@ENABLE_BITTORRENT_TRUE@ BtProgressInfoFile.h\
-@ENABLE_BITTORRENT_TRUE@ DefaultBtProgressInfoFile.cc DefaultBtProgressInfoFile.h\
@ENABLE_BITTORRENT_TRUE@ BtContextAwareCommand.cc BtContextAwareCommand.h\
@ENABLE_BITTORRENT_TRUE@ BtMessage.h\
@ENABLE_BITTORRENT_TRUE@ AbstractBtMessage.h\
@@ -152,14 +143,21 @@ bin_PROGRAMS = aria2c$(EXEEXT)
@ENABLE_BITTORRENT_TRUE@ DefaultBtInteractive.cc DefaultBtInteractive.h\
@ENABLE_BITTORRENT_TRUE@ PeerObject.h\
@ENABLE_BITTORRENT_TRUE@ ActivePeerConnectionCommand.cc ActivePeerConnectionCommand.h\
-@ENABLE_BITTORRENT_TRUE@ TrackerSegmentManFactory.cc TrackerSegmentManFactory.h
+@ENABLE_BITTORRENT_TRUE@ BtDependency.cc BtDependency.h\
+@ENABLE_BITTORRENT_TRUE@ PeerReceiveHandshakeCommand.cc PeerReceiveHandshakeCommand.h\
+@ENABLE_BITTORRENT_TRUE@ BtSetup.cc BtSetup.h\
+@ENABLE_BITTORRENT_TRUE@ BtFileAllocationEntry.cc BtFileAllocationEntry.h\
+@ENABLE_BITTORRENT_TRUE@ BtPostDownloadHandler.cc BtPostDownloadHandler.h\
+@ENABLE_BITTORRENT_TRUE@ MultiFileAllocationIterator.cc MultiFileAllocationIterator.h\
+@ENABLE_BITTORRENT_TRUE@ BtCheckIntegrityEntry.cc BtCheckIntegrityEntry.h
@ENABLE_METALINK_TRUE@am__append_3 = Metalinker.cc Metalinker.h\
@ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\
@ENABLE_METALINK_TRUE@ MetalinkResource.cc MetalinkResource.h\
@ENABLE_METALINK_TRUE@ MetalinkProcessor.h\
@ENABLE_METALINK_TRUE@ Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h\
-@ENABLE_METALINK_TRUE@ MetalinkRequestInfo.cc MetalinkRequestInfo.h
+@ENABLE_METALINK_TRUE@ Metalink2RequestGroup.cc Metalink2RequestGroup.h\
+@ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.cc MetalinkPostDownloadHandler.h
@HAVE_BASENAME_FALSE@am__append_4 = libgen.c libgen.h
@HAVE_GETADDRINFO_FALSE@am__append_5 = getaddrinfo.c getaddrinfo.h
@@ -213,8 +211,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
FtpDownloadCommand.h FtpTunnelRequestCommand.cc \
FtpTunnelRequestCommand.h FtpTunnelResponseCommand.cc \
FtpTunnelResponseCommand.h SleepCommand.cc SleepCommand.h \
- DownloadEngine.cc DownloadEngine.h ConsoleDownloadEngine.cc \
- ConsoleDownloadEngine.h Segment.cc Segment.h SegmentMan.cc \
+ DownloadEngine.cc DownloadEngine.h Segment.h GrowSegment.cc \
+ GrowSegment.h PiecedSegment.cc PiecedSegment.h SegmentMan.cc \
SegmentMan.h Util.cc Util.h Request.cc Request.h common.h \
message.h Exception.h FatalException.h RecoverableException.h \
DlAbortEx.h DlRetryEx.h Logger.h SimpleLogger.cc \
@@ -229,25 +227,24 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
SpeedCalc.cc SpeedCalc.h PeerStat.h BitfieldMan.cc \
BitfieldMan.h BitfieldManFactory.cc BitfieldManFactory.h \
Randomizer.h SimpleRandomizer.cc SimpleRandomizer.h \
- FileAllocator.h FileAllocationMonitor.cc \
- FileAllocationMonitor.h ConsoleFileAllocationMonitor.cc \
- ConsoleFileAllocationMonitor.h HttpResponse.cc HttpResponse.h \
- HttpRequest.cc HttpRequest.h Range.h \
- AbstractProxyRequestCommand.cc AbstractProxyRequestCommand.h \
- AbstractProxyResponseCommand.cc AbstractProxyResponseCommand.h \
- Netrc.cc Netrc.h AuthConfig.cc AuthConfig.h AuthResolver.h \
- AbstractAuthResolver.h DefaultAuthResolver.cc \
- DefaultAuthResolver.h NetrcAuthResolver.cc NetrcAuthResolver.h \
- RequestFactory.cc RequestFactory.h DefaultFileAllocator.cc \
- DefaultFileAllocator.h GlowFileAllocator.cc \
- GlowFileAllocator.h OptionParser.cc OptionParser.h \
+ FileAllocator.h HttpResponse.cc HttpResponse.h HttpRequest.cc \
+ HttpRequest.h Range.h AbstractProxyRequestCommand.cc \
+ AbstractProxyRequestCommand.h AbstractProxyResponseCommand.cc \
+ AbstractProxyResponseCommand.h Netrc.cc Netrc.h AuthConfig.cc \
+ AuthConfig.h AuthResolver.h AbstractAuthResolver.h \
+ DefaultAuthResolver.cc DefaultAuthResolver.h \
+ NetrcAuthResolver.cc NetrcAuthResolver.h RequestFactory.cc \
+ RequestFactory.h OptionParser.cc OptionParser.h \
OptionHandlerFactory.cc OptionHandlerFactory.h NameResolver.cc \
NameResolver.h RequestGroup.cc RequestGroup.h \
- RequestGroupMan.cc RequestGroupMan.h FileAllocationCommand.cc \
- FileAllocationCommand.h FillRequestGroupCommand.cc \
- FillRequestGroupCommand.h FileAllocationDispatcherCommand.cc \
+ RequestGroupAware.cc RequestGroupAware.h RequestGroupMan.cc \
+ RequestGroupMan.h FileAllocationMan.cc FileAllocationMan.h \
+ FileAllocationCommand.cc FileAllocationCommand.h \
+ FillRequestGroupCommand.cc FillRequestGroupCommand.h \
+ FileAllocationDispatcherCommand.cc \
FileAllocationDispatcherCommand.h FileAllocationEntry.cc \
- FileAllocationEntry.h MultiUrlRequestInfo.cc \
+ FileAllocationEntry.h StreamFileAllocationEntry.cc \
+ StreamFileAllocationEntry.h MultiUrlRequestInfo.cc \
MultiUrlRequestInfo.h UriListParser.cc UriListParser.h \
SegmentManFactory.h AbstractSegmentManFactory.h \
DefaultSegmentManFactory.cc DefaultSegmentManFactory.h \
@@ -262,47 +259,49 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
ParameterizedStringParser.cc ParameterizedStringParser.h \
FixedWidthNumberDecorator.h NumberDecorator.h \
AlphaNumberDecorator.h TimeBasedCommand.cc TimeBasedCommand.h \
- AutoSaveCommand.cc AutoSaveCommand.h ChunkChecksumValidator.cc \
- ChunkChecksumValidator.h IteratableChunkChecksumValidator.cc \
+ AutoSaveCommand.cc AutoSaveCommand.h \
+ UnknownLengthPieceStorage.cc UnknownLengthPieceStorage.h \
+ StatCalc.h ConsoleStatCalc.cc ConsoleStatCalc.h \
+ TransferStat.cc TransferStat.h Dependency.h \
+ BtProgressInfoFile.h DefaultBtProgressInfoFile.cc \
+ DefaultBtProgressInfoFile.h NullProgressInfoFile.h \
+ FileAllocationIterator.h SingleFileAllocationIterator.cc \
+ SingleFileAllocationIterator.h PostDownloadHandler.cc \
+ PostDownloadHandler.h HaveEraseCommand.cc HaveEraseCommand.h \
+ Piece.cc Piece.h IteratableChunkChecksumValidator.cc \
IteratableChunkChecksumValidator.h \
IteratableChecksumValidator.cc IteratableChecksumValidator.h \
ChecksumCommand.cc ChecksumCommand.h CheckIntegrityCommand.cc \
CheckIntegrityCommand.h CheckIntegrityEntry.cc \
- CheckIntegrityEntry.h CheckIntegrityMan.h messageDigest.cc \
- messageDigest.h MessageDigestHelper.cc MessageDigestHelper.h \
- MetaEntry.h Data.cc Data.h Dictionary.cc Dictionary.h List.cc \
- List.h MetaFileUtil.cc MetaFileUtil.h MetaEntryVisitor.h \
+ CheckIntegrityEntry.h StreamCheckIntegrityEntry.cc \
+ StreamCheckIntegrityEntry.h CheckIntegrityMan.cc \
+ CheckIntegrityMan.h messageDigest.cc messageDigest.h \
+ MessageDigestHelper.cc MessageDigestHelper.h MetaEntry.h \
+ Data.cc Data.h Dictionary.cc Dictionary.h List.cc List.h \
+ MetaFileUtil.cc MetaFileUtil.h MetaEntryVisitor.h \
ShaVisitor.cc ShaVisitor.h PeerConnection.cc PeerConnection.h \
PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \
PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \
PeerInitiateConnectionCommand.h PeerInteractionCommand.cc \
- PeerInteractionCommand.h Peer.cc Peer.h \
- TorrentDownloadEngine.cc TorrentDownloadEngine.h \
- TorrentConsoleDownloadEngine.cc TorrentConsoleDownloadEngine.h \
- PeerListenCommand.cc PeerListenCommand.h Piece.cc Piece.h \
- RequestSlot.cc RequestSlot.h TorrentAutoSaveCommand.cc \
- TorrentAutoSaveCommand.h Directory.cc Directory.h \
- TrackerWatcherCommand.cc TrackerWatcherCommand.h \
+ PeerInteractionCommand.h Peer.cc Peer.h PeerListenCommand.cc \
+ PeerListenCommand.h RequestSlot.cc RequestSlot.h Directory.cc \
+ Directory.h TrackerWatcherCommand.cc TrackerWatcherCommand.h \
DiskAdaptor.cc DiskAdaptor.h AbstractSingleDiskAdaptor.cc \
AbstractSingleDiskAdaptor.h CopyDiskAdaptor.cc \
CopyDiskAdaptor.h DirectDiskAdaptor.cc DirectDiskAdaptor.h \
- MultiDiskAdaptor.cc MultiDiskAdaptor.h TrackerUpdateCommand.cc \
- TrackerUpdateCommand.h ByteArrayDiskWriter.cc \
+ MultiDiskAdaptor.cc MultiDiskAdaptor.h ByteArrayDiskWriter.cc \
ByteArrayDiskWriter.h PeerChokeCommand.cc PeerChokeCommand.h \
- HaveEraseCommand.cc HaveEraseCommand.h TorrentRequestInfo.cc \
- TorrentRequestInfo.h SeedCriteria.h TimeSeedCriteria.h \
- ShareRatioSeedCriteria.h UnionSeedCriteria.h \
- SeedCheckCommand.cc SeedCheckCommand.h PeerListProcessor.h \
- DefaultPeerListProcessor.cc DefaultPeerListProcessor.h \
- CompactPeerListProcessor.cc CompactPeerListProcessor.h \
- DelegatingPeerListProcessor.cc DelegatingPeerListProcessor.h \
- AnnounceTier.h AnnounceList.h AnnounceList.cc BtContext.h \
- DefaultBtContext.cc DefaultBtContext.h PieceStorage.h \
- DefaultPieceStorage.cc DefaultPieceStorage.h \
- DefaultPeerStorage.cc DefaultPeerStorage.h BtAnnounce.h \
- DefaultBtAnnounce.cc DefaultBtAnnounce.h BtRegistry.cc \
- BtRegistry.h BtRuntime.h BtProgressInfoFile.h \
- DefaultBtProgressInfoFile.cc DefaultBtProgressInfoFile.h \
+ SeedCriteria.h TimeSeedCriteria.h ShareRatioSeedCriteria.h \
+ UnionSeedCriteria.h SeedCheckCommand.cc SeedCheckCommand.h \
+ PeerListProcessor.h DefaultPeerListProcessor.cc \
+ DefaultPeerListProcessor.h CompactPeerListProcessor.cc \
+ CompactPeerListProcessor.h DelegatingPeerListProcessor.cc \
+ DelegatingPeerListProcessor.h AnnounceTier.h AnnounceList.h \
+ AnnounceList.cc BtContext.h DefaultBtContext.cc \
+ DefaultBtContext.h PieceStorage.h DefaultPieceStorage.cc \
+ DefaultPieceStorage.h DefaultPeerStorage.cc \
+ DefaultPeerStorage.h BtAnnounce.h DefaultBtAnnounce.cc \
+ DefaultBtAnnounce.h BtRegistry.cc BtRegistry.h BtRuntime.h \
BtContextAwareCommand.cc BtContextAwareCommand.h BtMessage.h \
AbstractBtMessage.h SimpleBtMessage.cc SimpleBtMessage.h \
BtAllowedFastMessage.cc BtAllowedFastMessage.h \
@@ -334,22 +333,28 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
BtChokedEvent.h BtChokingEvent.h BtInteractive.h \
DefaultBtInteractive.cc DefaultBtInteractive.h PeerObject.h \
ActivePeerConnectionCommand.cc ActivePeerConnectionCommand.h \
- TrackerSegmentManFactory.cc TrackerSegmentManFactory.h \
- Metalinker.cc Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
+ BtDependency.cc BtDependency.h PeerReceiveHandshakeCommand.cc \
+ PeerReceiveHandshakeCommand.h BtSetup.cc BtSetup.h \
+ BtFileAllocationEntry.cc BtFileAllocationEntry.h \
+ BtPostDownloadHandler.cc BtPostDownloadHandler.h \
+ MultiFileAllocationIterator.cc MultiFileAllocationIterator.h \
+ BtCheckIntegrityEntry.cc BtCheckIntegrityEntry.h Metalinker.cc \
+ Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \
Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h \
- MetalinkRequestInfo.cc MetalinkRequestInfo.h libgen.c libgen.h \
- getaddrinfo.c getaddrinfo.h gai_strerror.c gai_strerror.h \
- gettimeofday.c gettimeofday.h inet_aton.c inet_aton.h \
- localtime_r.c localtime_r.h strptime.c strptime.h timegm.c \
- timegm.h
-@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = \
-@ENABLE_MESSAGE_DIGEST_TRUE@ ChunkChecksumValidator.$(OBJEXT) \
-@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidator.$(OBJEXT) \
+ Metalink2RequestGroup.cc Metalink2RequestGroup.h \
+ MetalinkPostDownloadHandler.cc MetalinkPostDownloadHandler.h \
+ libgen.c libgen.h getaddrinfo.c getaddrinfo.h gai_strerror.c \
+ gai_strerror.h gettimeofday.c gettimeofday.h inet_aton.c \
+ inet_aton.h localtime_r.c localtime_r.h strptime.c strptime.h \
+ timegm.c timegm.h
+@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = IteratableChunkChecksumValidator.$(OBJEXT) \
@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidator.$(OBJEXT) \
@ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCommand.$(OBJEXT) \
@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.$(OBJEXT) \
@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityEntry.$(OBJEXT) \
+@ENABLE_MESSAGE_DIGEST_TRUE@ StreamCheckIntegrityEntry.$(OBJEXT) \
+@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityMan.$(OBJEXT) \
@ENABLE_MESSAGE_DIGEST_TRUE@ messageDigest.$(OBJEXT) \
@ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelper.$(OBJEXT)
@ENABLE_BITTORRENT_TRUE@am__objects_2 = Data.$(OBJEXT) \
@@ -362,11 +367,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
@ENABLE_BITTORRENT_TRUE@ PeerInitiateConnectionCommand.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ PeerInteractionCommand.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ Peer.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@ TorrentDownloadEngine.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@ TorrentConsoleDownloadEngine.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ PeerListenCommand.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@ Piece.$(OBJEXT) RequestSlot.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@ TorrentAutoSaveCommand.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ RequestSlot.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ Directory.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ TrackerWatcherCommand.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DiskAdaptor.$(OBJEXT) \
@@ -374,11 +376,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
@ENABLE_BITTORRENT_TRUE@ CopyDiskAdaptor.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DirectDiskAdaptor.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ MultiDiskAdaptor.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@ TrackerUpdateCommand.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ ByteArrayDiskWriter.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ PeerChokeCommand.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@ HaveEraseCommand.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@ TorrentRequestInfo.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ SeedCheckCommand.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DefaultPeerListProcessor.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ CompactPeerListProcessor.$(OBJEXT) \
@@ -389,7 +388,6 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
@ENABLE_BITTORRENT_TRUE@ DefaultPeerStorage.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DefaultBtAnnounce.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BtRegistry.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@ DefaultBtProgressInfoFile.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BtContextAwareCommand.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ SimpleBtMessage.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BtAllowedFastMessage.$(OBJEXT) \
@@ -415,12 +413,19 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
@ENABLE_BITTORRENT_TRUE@ DefaultBtRequestFactory.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DefaultBtInteractive.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ ActivePeerConnectionCommand.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@ TrackerSegmentManFactory.$(OBJEXT)
+@ENABLE_BITTORRENT_TRUE@ BtDependency.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ PeerReceiveHandshakeCommand.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ BtSetup.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ BtFileAllocationEntry.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ BtPostDownloadHandler.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ MultiFileAllocationIterator.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ BtCheckIntegrityEntry.$(OBJEXT)
@ENABLE_METALINK_TRUE@am__objects_3 = Metalinker.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ Xml2MetalinkProcessor.$(OBJEXT) \
-@ENABLE_METALINK_TRUE@ MetalinkRequestInfo.$(OBJEXT)
+@ENABLE_METALINK_TRUE@ Metalink2RequestGroup.$(OBJEXT) \
+@ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.$(OBJEXT)
@HAVE_BASENAME_FALSE@am__objects_4 = libgen.$(OBJEXT)
@HAVE_GETADDRINFO_FALSE@am__objects_5 = getaddrinfo.$(OBJEXT)
@HAVE_GAI_STRERROR_FALSE@am__objects_6 = gai_strerror.$(OBJEXT)
@@ -444,8 +449,8 @@ am__objects_12 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
FtpNegotiationCommand.$(OBJEXT) FtpDownloadCommand.$(OBJEXT) \
FtpTunnelRequestCommand.$(OBJEXT) \
FtpTunnelResponseCommand.$(OBJEXT) SleepCommand.$(OBJEXT) \
- DownloadEngine.$(OBJEXT) ConsoleDownloadEngine.$(OBJEXT) \
- Segment.$(OBJEXT) SegmentMan.$(OBJEXT) Util.$(OBJEXT) \
+ DownloadEngine.$(OBJEXT) GrowSegment.$(OBJEXT) \
+ PiecedSegment.$(OBJEXT) SegmentMan.$(OBJEXT) Util.$(OBJEXT) \
Request.$(OBJEXT) SimpleLogger.$(OBJEXT) \
ChunkedEncoding.$(OBJEXT) AbstractDiskWriter.$(OBJEXT) \
DefaultDiskWriter.$(OBJEXT) File.$(OBJEXT) Option.$(OBJEXT) \
@@ -453,27 +458,33 @@ am__objects_12 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
TimeA2.$(OBJEXT) FeatureConfig.$(OBJEXT) \
DownloadEngineFactory.$(OBJEXT) SpeedCalc.$(OBJEXT) \
BitfieldMan.$(OBJEXT) BitfieldManFactory.$(OBJEXT) \
- SimpleRandomizer.$(OBJEXT) FileAllocationMonitor.$(OBJEXT) \
- ConsoleFileAllocationMonitor.$(OBJEXT) HttpResponse.$(OBJEXT) \
+ SimpleRandomizer.$(OBJEXT) HttpResponse.$(OBJEXT) \
HttpRequest.$(OBJEXT) AbstractProxyRequestCommand.$(OBJEXT) \
AbstractProxyResponseCommand.$(OBJEXT) Netrc.$(OBJEXT) \
AuthConfig.$(OBJEXT) DefaultAuthResolver.$(OBJEXT) \
NetrcAuthResolver.$(OBJEXT) RequestFactory.$(OBJEXT) \
- DefaultFileAllocator.$(OBJEXT) GlowFileAllocator.$(OBJEXT) \
OptionParser.$(OBJEXT) OptionHandlerFactory.$(OBJEXT) \
NameResolver.$(OBJEXT) RequestGroup.$(OBJEXT) \
- RequestGroupMan.$(OBJEXT) FileAllocationCommand.$(OBJEXT) \
+ RequestGroupAware.$(OBJEXT) RequestGroupMan.$(OBJEXT) \
+ FileAllocationMan.$(OBJEXT) FileAllocationCommand.$(OBJEXT) \
FillRequestGroupCommand.$(OBJEXT) \
FileAllocationDispatcherCommand.$(OBJEXT) \
- FileAllocationEntry.$(OBJEXT) MultiUrlRequestInfo.$(OBJEXT) \
- UriListParser.$(OBJEXT) DefaultSegmentManFactory.$(OBJEXT) \
- RealtimeCommand.$(OBJEXT) RequestGroupEntry.$(OBJEXT) \
- Cookie.$(OBJEXT) CookieParser.$(OBJEXT) \
- CookieBoxFactory.$(OBJEXT) HttpHeaderProcessor.$(OBJEXT) \
- FileEntry.$(OBJEXT) Platform.$(OBJEXT) \
- PStringSegment.$(OBJEXT) PStringBuildVisitor.$(OBJEXT) \
+ FileAllocationEntry.$(OBJEXT) \
+ StreamFileAllocationEntry.$(OBJEXT) \
+ MultiUrlRequestInfo.$(OBJEXT) UriListParser.$(OBJEXT) \
+ DefaultSegmentManFactory.$(OBJEXT) RealtimeCommand.$(OBJEXT) \
+ RequestGroupEntry.$(OBJEXT) Cookie.$(OBJEXT) \
+ CookieParser.$(OBJEXT) CookieBoxFactory.$(OBJEXT) \
+ HttpHeaderProcessor.$(OBJEXT) FileEntry.$(OBJEXT) \
+ Platform.$(OBJEXT) PStringSegment.$(OBJEXT) \
+ PStringBuildVisitor.$(OBJEXT) \
ParameterizedStringParser.$(OBJEXT) TimeBasedCommand.$(OBJEXT) \
- AutoSaveCommand.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
+ AutoSaveCommand.$(OBJEXT) UnknownLengthPieceStorage.$(OBJEXT) \
+ ConsoleStatCalc.$(OBJEXT) TransferStat.$(OBJEXT) \
+ DefaultBtProgressInfoFile.$(OBJEXT) \
+ SingleFileAllocationIterator.$(OBJEXT) \
+ PostDownloadHandler.$(OBJEXT) HaveEraseCommand.$(OBJEXT) \
+ Piece.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
$(am__objects_3) $(am__objects_4) $(am__objects_5) \
$(am__objects_6) $(am__objects_7) $(am__objects_8) \
$(am__objects_9) $(am__objects_10) $(am__objects_11)
@@ -482,7 +493,8 @@ libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
am__installdirs = "$(DESTDIR)$(bindir)"
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
-am_aria2c_OBJECTS = main.$(OBJEXT)
+am_aria2c_OBJECTS = main.$(OBJEXT) option_processing.$(OBJEXT) \
+ version_usage.$(OBJEXT)
aria2c_OBJECTS = $(am_aria2c_OBJECTS)
aria2c_DEPENDENCIES = libaria2c.a @ALLOCA@
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
@@ -667,7 +679,10 @@ target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
-aria2c_SOURCES = main.cc
+aria2c_SOURCES = main.cc\
+ option_processing.cc\
+ version_usage.cc
+
SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \
AbstractCommand.cc AbstractCommand.h \
InitiateConnectionCommandFactory.cc \
@@ -686,8 +701,8 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \
FtpDownloadCommand.h FtpTunnelRequestCommand.cc \
FtpTunnelRequestCommand.h FtpTunnelResponseCommand.cc \
FtpTunnelResponseCommand.h SleepCommand.cc SleepCommand.h \
- DownloadEngine.cc DownloadEngine.h ConsoleDownloadEngine.cc \
- ConsoleDownloadEngine.h Segment.cc Segment.h SegmentMan.cc \
+ DownloadEngine.cc DownloadEngine.h Segment.h GrowSegment.cc \
+ GrowSegment.h PiecedSegment.cc PiecedSegment.h SegmentMan.cc \
SegmentMan.h Util.cc Util.h Request.cc Request.h common.h \
message.h Exception.h FatalException.h RecoverableException.h \
DlAbortEx.h DlRetryEx.h Logger.h SimpleLogger.cc \
@@ -702,25 +717,24 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \
SpeedCalc.cc SpeedCalc.h PeerStat.h BitfieldMan.cc \
BitfieldMan.h BitfieldManFactory.cc BitfieldManFactory.h \
Randomizer.h SimpleRandomizer.cc SimpleRandomizer.h \
- FileAllocator.h FileAllocationMonitor.cc \
- FileAllocationMonitor.h ConsoleFileAllocationMonitor.cc \
- ConsoleFileAllocationMonitor.h HttpResponse.cc HttpResponse.h \
- HttpRequest.cc HttpRequest.h Range.h \
- AbstractProxyRequestCommand.cc AbstractProxyRequestCommand.h \
- AbstractProxyResponseCommand.cc AbstractProxyResponseCommand.h \
- Netrc.cc Netrc.h AuthConfig.cc AuthConfig.h AuthResolver.h \
- AbstractAuthResolver.h DefaultAuthResolver.cc \
- DefaultAuthResolver.h NetrcAuthResolver.cc NetrcAuthResolver.h \
- RequestFactory.cc RequestFactory.h DefaultFileAllocator.cc \
- DefaultFileAllocator.h GlowFileAllocator.cc \
- GlowFileAllocator.h OptionParser.cc OptionParser.h \
+ FileAllocator.h HttpResponse.cc HttpResponse.h HttpRequest.cc \
+ HttpRequest.h Range.h AbstractProxyRequestCommand.cc \
+ AbstractProxyRequestCommand.h AbstractProxyResponseCommand.cc \
+ AbstractProxyResponseCommand.h Netrc.cc Netrc.h AuthConfig.cc \
+ AuthConfig.h AuthResolver.h AbstractAuthResolver.h \
+ DefaultAuthResolver.cc DefaultAuthResolver.h \
+ NetrcAuthResolver.cc NetrcAuthResolver.h RequestFactory.cc \
+ RequestFactory.h OptionParser.cc OptionParser.h \
OptionHandlerFactory.cc OptionHandlerFactory.h NameResolver.cc \
NameResolver.h RequestGroup.cc RequestGroup.h \
- RequestGroupMan.cc RequestGroupMan.h FileAllocationCommand.cc \
- FileAllocationCommand.h FillRequestGroupCommand.cc \
- FillRequestGroupCommand.h FileAllocationDispatcherCommand.cc \
+ RequestGroupAware.cc RequestGroupAware.h RequestGroupMan.cc \
+ RequestGroupMan.h FileAllocationMan.cc FileAllocationMan.h \
+ FileAllocationCommand.cc FileAllocationCommand.h \
+ FillRequestGroupCommand.cc FillRequestGroupCommand.h \
+ FileAllocationDispatcherCommand.cc \
FileAllocationDispatcherCommand.h FileAllocationEntry.cc \
- FileAllocationEntry.h MultiUrlRequestInfo.cc \
+ FileAllocationEntry.h StreamFileAllocationEntry.cc \
+ StreamFileAllocationEntry.h MultiUrlRequestInfo.cc \
MultiUrlRequestInfo.h UriListParser.cc UriListParser.h \
SegmentManFactory.h AbstractSegmentManFactory.h \
DefaultSegmentManFactory.cc DefaultSegmentManFactory.h \
@@ -735,23 +749,31 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \
ParameterizedStringParser.cc ParameterizedStringParser.h \
FixedWidthNumberDecorator.h NumberDecorator.h \
AlphaNumberDecorator.h TimeBasedCommand.cc TimeBasedCommand.h \
- AutoSaveCommand.cc AutoSaveCommand.h $(am__append_1) \
- $(am__append_2) $(am__append_3) $(am__append_4) \
- $(am__append_5) $(am__append_6) $(am__append_7) \
- $(am__append_8) $(am__append_9) $(am__append_10) \
- $(am__append_11)
+ AutoSaveCommand.cc AutoSaveCommand.h \
+ UnknownLengthPieceStorage.cc UnknownLengthPieceStorage.h \
+ StatCalc.h ConsoleStatCalc.cc ConsoleStatCalc.h \
+ TransferStat.cc TransferStat.h Dependency.h \
+ BtProgressInfoFile.h DefaultBtProgressInfoFile.cc \
+ DefaultBtProgressInfoFile.h NullProgressInfoFile.h \
+ FileAllocationIterator.h SingleFileAllocationIterator.cc \
+ SingleFileAllocationIterator.h PostDownloadHandler.cc \
+ PostDownloadHandler.h HaveEraseCommand.cc HaveEraseCommand.h \
+ Piece.cc Piece.h $(am__append_1) $(am__append_2) \
+ $(am__append_3) $(am__append_4) $(am__append_5) \
+ $(am__append_6) $(am__append_7) $(am__append_8) \
+ $(am__append_9) $(am__append_10) $(am__append_11)
noinst_LIBRARIES = libaria2c.a
libaria2c_a_SOURCES = $(SRCS)
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
@LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@ @LIBARES_LIBS@\
- @LIBCARES_LIBS@ @WINSOCK_LIBS@ # -lprofiler
+ @LIBCARES_LIBS@ @WINSOCK_LIBS@ #-lprofiler
-#aria2c_LDFLAGS = #-pg
+#aria2c_LDFLAGS = -pg
AM_CPPFLAGS = -Wall\
-I../lib -I../intl -I$(top_srcdir)/intl\
@LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\
@LIBARES_CPPFLAGS@ @LIBCARES_CPPFLAGS@\
- -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ # -pg
+ -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ #-pg
all: all-am
@@ -842,8 +864,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtAllowedFastMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtBitfieldMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtCancelMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtCheckIntegrityEntry.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtChokeMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtContextAwareCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtDependency.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtFileAllocationEntry.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHandshakeMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHaveAllMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHaveMessage.Po@am__quote@
@@ -853,21 +878,22 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtNotInterestedMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtPieceMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtPortMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtPostDownloadHandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRegistry.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRejectMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRequestMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtSetup.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtSuggestPieceMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtUnchokeMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ByteArrayDiskWriter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CheckIntegrityCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CheckIntegrityEntry.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CheckIntegrityMan.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChecksumCommand.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChunkChecksumValidator.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChunkedEncoding.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Command.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompactPeerListProcessor.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConsoleDownloadEngine.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConsoleFileAllocationMonitor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConsoleStatCalc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Cookie.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBox.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBoxFactory.Po@am__quote@
@@ -884,7 +910,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtProgressInfoFile.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtRequestFactory.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultDiskWriter.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultFileAllocator.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPeerListProcessor.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPeerStorage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPieceStorage.Po@am__quote@
@@ -902,7 +927,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileAllocationCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileAllocationDispatcherCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileAllocationEntry.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileAllocationMonitor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileAllocationMan.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileEntry.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FillRequestGroupCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpConnection.Po@am__quote@
@@ -911,7 +936,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpNegotiationCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpTunnelRequestCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpTunnelResponseCommand.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GlowFileAllocator.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GrowSegment.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HaveEraseCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpConnection.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpDownloadCommand.Po@am__quote@
@@ -931,11 +956,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LogFactory.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MessageDigestHelper.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetaFileUtil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Metalink2RequestGroup.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkEntry.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkRequestInfo.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkPostDownloadHandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkResource.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Metalinker.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultiDiskAdaptor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultiFileAllocationIterator.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultiUrlRequestInfo.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NameResolver.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Netrc.Po@am__quote@
@@ -954,34 +981,36 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerInteractionCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerListenCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerMessageUtil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerReceiveHandshakeCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Piece.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PiecedSegment.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Platform.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PostDownloadHandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RealtimeCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Request.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestFactory.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestGroup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestGroupAware.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestGroupEntry.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestGroupMan.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestSlot.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SeedCheckCommand.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Segment.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentMan.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShaVisitor.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleBtMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleLogger.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleRandomizer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SingleFileAllocationIterator.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SleepCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketCore.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SpeedCalc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StreamCheckIntegrityEntry.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StreamFileAllocationEntry.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeA2.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeBasedCommand.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentAutoSaveCommand.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentConsoleDownloadEngine.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentDownloadEngine.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentRequestInfo.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerSegmentManFactory.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerUpdateCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerWatcherCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TransferStat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UnknownLengthPieceStorage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UriListParser.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Util.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xml2MetalinkProcessor.Po@am__quote@
@@ -993,8 +1022,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localtime_r.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/messageDigest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/option_processing.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strptime.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timegm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version_usage.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
diff --git a/src/MessageDigestHelper.cc b/src/MessageDigestHelper.cc
index 8819dcdc..edda3c6c 100644
--- a/src/MessageDigestHelper.cc
+++ b/src/MessageDigestHelper.cc
@@ -40,18 +40,21 @@
#include "Util.h"
#include <errno.h>
-string MessageDigestHelper::digest(const string& algo, DiskWriterHandle diskWriter, int64_t offset, int64_t length)
+string MessageDigestHelper::digest(const string& algo,
+ const BinaryStreamHandle& bs,
+ int64_t offset,
+ int64_t length)
{
MessageDigestContext ctx;
ctx.trySetAlgo(algo);
ctx.digestInit();
int32_t BUFSIZE = 4096;
- char BUF[BUFSIZE];
+ unsigned char BUF[BUFSIZE];
int64_t iteration = length/BUFSIZE;
int32_t tail = length%BUFSIZE;
for(int64_t i = 0; i < iteration; ++i) {
- int32_t readLength = diskWriter->readData(BUF, BUFSIZE, offset);
+ int32_t readLength = bs->readData(BUF, BUFSIZE, offset);
if(readLength != BUFSIZE) {
throw new DlAbortEx(EX_FILE_READ, "n/a", strerror(errno));
}
@@ -59,7 +62,7 @@ string MessageDigestHelper::digest(const string& algo, DiskWriterHandle diskWrit
offset += readLength;
}
if(tail) {
- int32_t readLength = diskWriter->readData(BUF, tail, offset);
+ int32_t readLength = bs->readData(BUF, tail, offset);
if(readLength != tail) {
throw new DlAbortEx(EX_FILE_READ, "n/a", strerror(errno));
}
@@ -73,7 +76,7 @@ string MessageDigestHelper::digest(const string& algo, const string& filename)
{
DiskWriterHandle writer = new DefaultDiskWriter();
writer->openExistingFile(filename);
- return digest(algo, writer);
+ return digest(algo, writer, 0, writer->size());
}
string MessageDigestHelper::digest(const string& algo, const void* data, int32_t length)
diff --git a/src/MessageDigestHelper.h b/src/MessageDigestHelper.h
index 21e4a215..04a7c155 100644
--- a/src/MessageDigestHelper.h
+++ b/src/MessageDigestHelper.h
@@ -36,7 +36,7 @@
#define _D_MESSAGE_DIGEST_HELPER_H_
#include "common.h"
-#include "DiskWriter.h"
+#include "BinaryStream.h"
class MessageDigestHelper {
public:
@@ -44,15 +44,7 @@ public:
* Returns message digest in hexadecimal notation.
* Digest algorithm is specified by algo.
*/
- static string digest(const string& algo, DiskWriterHandle diskWriter, int64_t offset, int64_t length);
-
- /**
- * Calculates message digest of file opened by diskWriter.
- */
- static string digest(const string& algo, DiskWriterHandle diskWriter)
- {
- return digest(algo, diskWriter, 0, diskWriter->size());
- }
+ static string digest(const string& algo, const BinaryStreamHandle& bs, int64_t offset, int64_t length);
/**
* Calculates message digest of file denoted by filename.
diff --git a/src/MetalinkRequestInfo.cc b/src/Metalink2RequestGroup.cc
index 7e2311ef..7985af99 100644
--- a/src/MetalinkRequestInfo.cc
+++ b/src/Metalink2RequestGroup.cc
@@ -32,13 +32,21 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
-#include "MetalinkRequestInfo.h"
-#include "Xml2MetalinkProcessor.h"
+#include "Metalink2RequestGroup.h"
+#include "RequestGroup.h"
+#include "Option.h"
+#include "LogFactory.h"
#include "prefs.h"
-#include "DlAbortEx.h"
-#include "MultiUrlRequestInfo.h"
+#include "Xml2MetalinkProcessor.h"
#include "Util.h"
#include "message.h"
+#include "RecoverableException.h"
+#include "BtDependency.h"
+#include "SingleFileDownloadContext.h"
+
+Metalink2RequestGroup::Metalink2RequestGroup(const Option* option):_option(option), _logger(LogFactory::getInstance()) {}
+
+Metalink2RequestGroup::~Metalink2RequestGroup() {}
class AccumulateNonP2PUrl {
private:
@@ -83,26 +91,21 @@ public:
}
};
-RequestInfos MetalinkRequestInfo::execute() {
+RequestGroups Metalink2RequestGroup::generate(const string& metalinkFile)
+{
Xml2MetalinkProcessor proc;
- RequestInfos nextReqInfos;
try {
MetalinkerHandle metalinker = proc.parseFile(metalinkFile);
MetalinkEntries entries =
- metalinker->queryEntry(op->get(PREF_METALINK_VERSION),
- op->get(PREF_METALINK_LANGUAGE),
- op->get(PREF_METALINK_OS));
+ metalinker->queryEntry(_option->get(PREF_METALINK_VERSION),
+ _option->get(PREF_METALINK_LANGUAGE),
+ _option->get(PREF_METALINK_OS));
if(entries.size() == 0) {
- cout << EX_NO_RESULT_WITH_YOUR_PREFS << endl;
- throw new DlAbortEx(EX_NO_RESULT_WITH_YOUR_PREFS);
- }
- if(op->get(PREF_SHOW_FILES) == V_TRUE) {
- Util::toStream(cout, MetalinkEntry::toFileEntry(entries));
- return RequestInfos();
+ return RequestGroups();
}
bool useIndex;
Integers selectIndexes;
- Util::unfoldRange(op->get(PREF_SELECT_FILE), selectIndexes);
+ Util::unfoldRange(_option->get(PREF_SELECT_FILE), selectIndexes);
if(selectIndexes.size()) {
useIndex = true;
} else {
@@ -113,74 +116,80 @@ RequestInfos MetalinkRequestInfo::execute() {
for(MetalinkEntries::iterator itr = entries.begin(); itr != entries.end();
itr++, ++count) {
MetalinkEntryHandle& entry = *itr;
- if(op->defined(PREF_METALINK_LOCATION)) {
- entry->setLocationPreference(op->get(PREF_METALINK_LOCATION), 100);
+ if(_option->defined(PREF_METALINK_LOCATION)) {
+ entry->setLocationPreference(_option->get(PREF_METALINK_LOCATION), 100);
}
if(useIndex) {
if(find(selectIndexes.begin(), selectIndexes.end(), count+1) == selectIndexes.end()) {
continue;
}
- } else if(!targetFiles.empty()) {
- if(find(targetFiles.begin(), targetFiles.end(), entry->getPath()) == targetFiles.end()) {
- continue;
- }
}
-
entry->dropUnsupportedResource();
if(entry->resources.size() == 0) {
continue;
}
- logger->info(MSG_METALINK_QUEUEING,
- entry->getPath().c_str());
- MetalinkResources::iterator itr =
- find_if(entry->resources.begin(),
- entry->resources.end(),
- FindBitTorrentUrl());
- Strings urls;
-#ifdef ENABLE_MESSAGE_DIGEST
- ChecksumHandle checksum = 0;
-#endif // ENABLE_MESSAGE_DIGEST
- if(itr == entry->resources.end()) {
- entry->reorderResourcesByPreference();
-
- for_each(entry->resources.begin(), entry->resources.end(),
- AccumulateNonP2PUrl(&urls, op->getAsInt(PREF_SPLIT)));
-#ifdef ENABLE_MESSAGE_DIGEST
- // TODO
- // set checksum
- checksum = entry->checksum;
-#endif // ENABLE_MESSAGE_DIGEST
+ _logger->info(MSG_METALINK_QUEUEING, entry->getPath().c_str());
+ MetalinkResources::iterator itr = find_if(entry->resources.begin(),
+ entry->resources.end(),
+ FindBitTorrentUrl());
+ RequestGroupHandle torrentRg = 0;
+ // there is torrent entry
+ if(itr != entry->resources.end()) {
+ Strings uris;
+ uris.push_back((*itr)->url);
+ torrentRg = new RequestGroup(_option, uris);
+ SingleFileDownloadContextHandle dctx =
+ new SingleFileDownloadContext(_option->getAsInt(PREF_SEGMENT_SIZE),
+ 0,
+ "");
+ dctx->setDir(_option->get(PREF_DIR));
+ torrentRg->setDownloadContext(dctx);
+ torrentRg->clearPostDowloadHandler();
+ groups.push_back(torrentRg);
+ }
+ entry->reorderResourcesByPreference();
+ Strings uris;
+ for_each(entry->resources.begin(), entry->resources.end(),
+ AccumulateNonP2PUrl(&uris, _option->getAsInt(PREF_SPLIT)));
+ RequestGroupHandle rg = new RequestGroup(_option, uris);
+ // If piece hash is specified in the metalink,
+ // make segment size equal to piece hash size.
+ int32_t pieceLength;
+ if(entry->chunkChecksum.isNull()) {
+ pieceLength = _option->getAsInt(PREF_SEGMENT_SIZE);
} else {
- // BitTorrent downloading
- urls.push_back((*itr)->url);
+ pieceLength = entry->chunkChecksum->getChecksumLength();
}
- RequestGroupHandle rg = new RequestGroup(urls, op);
- if(itr == entry->resources.end()) {
- rg->setHintFilename(entry->file->getBasename());
- rg->setHintTotalLength(entry->getLength());
+ SingleFileDownloadContextHandle dctx =
+ new SingleFileDownloadContext(pieceLength,
+ 0,
+ "");
+ dctx->setDir(_option->get(PREF_DIR));
+ if(!entry->chunkChecksum.isNull()) {
+ dctx->setPieceHashes(entry->chunkChecksum->getChecksums());
+ dctx->setPieceHashAlgo(entry->chunkChecksum->getAlgo());
}
- rg->setTopDir(entry->file->getDirname());
+ // TODO set checksum here to DownloadContext
+ // * hash and hash algorithm
+
+ rg->setDownloadContext(dctx);
+ rg->setHintFilename(entry->file->getBasename());
+ rg->setHintTotalLength(entry->getLength());
rg->setNumConcurrentCommand(entry->maxConnections < 0 ?
- op->getAsInt(PREF_METALINK_SERVERS) :
- min<int32_t>(op->getAsInt(PREF_METALINK_SERVERS), entry->maxConnections));
+ _option->getAsInt(PREF_METALINK_SERVERS) :
+ min<int32_t>(_option->getAsInt(PREF_METALINK_SERVERS), entry->maxConnections));
-#ifdef ENABLE_MESSAGE_DIGEST
- if(entry->chunkChecksum.isNull()) {
- rg->setChecksum(checksum);
- } else {
- rg->setChunkChecksum(entry->chunkChecksum);
+ // Inject depenency between rg and torrentRg here if torrentRg.isNull() == false
+ if(!torrentRg.isNull()) {
+ rg->dependsOn(new BtDependency(rg, torrentRg, _option));
}
-#endif // ENABLE_MESSAGE_DIGEST
- groups.push_front(rg);
+
+ groups.push_back(rg);
}
- // clear PREF_OUT, because PREF_OUT is a filename for metalink file itself.
- op->put(PREF_OUT, "");
- MultiUrlRequestInfoHandle reqInfo = new MultiUrlRequestInfo(groups, op);
- nextReqInfos.push_back(reqInfo);
+ return groups;
} catch(RecoverableException* ex) {
- logger->error(EX_EXCEPTION_CAUGHT, ex);
+ _logger->error(EX_EXCEPTION_CAUGHT, ex);
delete ex;
- fail = true;
+ return RequestGroups();
}
- return nextReqInfos;
}
diff --git a/src/MetalinkRequestInfo.h b/src/Metalink2RequestGroup.h
index c89c3787..1c72fee8 100644
--- a/src/MetalinkRequestInfo.h
+++ b/src/Metalink2RequestGroup.h
@@ -32,26 +32,28 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
-#ifndef _D_METALINK_REQUEST_INFO_H_
-#define _D_METALINK_REQUEST_INFO_H_
+#ifndef _D_METALINK_2_REQUEST_GROUP_H_
+#define _D_METALINK_2_REQUEST_GROUP_H_
-#include "RequestInfo.h"
+#include "common.h"
-class MetalinkRequestInfo : public RequestInfo {
+class Option;
+class Logger;
+class RequestGroup;
+extern typedef SharedHandle<RequestGroup> RequestGroupHandle;
+extern typedef deque<RequestGroupHandle> RequestGroups;
+
+class Metalink2RequestGroup {
private:
- string metalinkFile;
- Strings targetFiles;
+ const Option* _option;
+
+ const Logger* _logger;
public:
- MetalinkRequestInfo(const string& metalinkFile, Option* op):
- RequestInfo(op),
- metalinkFile(metalinkFile) {}
- virtual ~MetalinkRequestInfo() {}
+ Metalink2RequestGroup(const Option* option);
- virtual RequestInfos execute();
+ ~Metalink2RequestGroup();
- void setTargetFiles(const Strings& targetFiles) {
- this->targetFiles = targetFiles;
- }
+ RequestGroups generate(const string& metalinkFile);
};
-#endif // _D_METALINK_REQUEST_INFO_H_
+#endif // _D_METALINK_2_REQUEST_GROUP_H_
diff --git a/src/MetalinkPostDownloadHandler.cc b/src/MetalinkPostDownloadHandler.cc
new file mode 100644
index 00000000..de6e9695
--- /dev/null
+++ b/src/MetalinkPostDownloadHandler.cc
@@ -0,0 +1,48 @@
+/* <!-- 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 "MetalinkPostDownloadHandler.h"
+#include "RequestGroup.h"
+#include "Metalink2RequestGroup.h"
+
+MetalinkPostDownloadHandler::MetalinkPostDownloadHandler(const Option* option):
+ PostDownloadHandler(".metalink", option)
+{}
+
+MetalinkPostDownloadHandler::~MetalinkPostDownloadHandler() {}
+
+RequestGroups MetalinkPostDownloadHandler::getNextRequestGroups(const string& path)
+{
+ return Metalink2RequestGroup(_option).generate(path);
+}
diff --git a/src/MetalinkPostDownloadHandler.h b/src/MetalinkPostDownloadHandler.h
new file mode 100644
index 00000000..068f44c2
--- /dev/null
+++ b/src/MetalinkPostDownloadHandler.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_METALINK_POST_DOWNLOAD_HANDLER_H_
+#define _D_METALINK_POST_DOWNLOAD_HANDLER_H_
+
+#include "PostDownloadHandler.h"
+
+class MetalinkPostDownloadHandler:public PostDownloadHandler
+{
+public:
+ MetalinkPostDownloadHandler(const Option* option);
+
+ virtual ~MetalinkPostDownloadHandler();
+
+ virtual RequestGroups getNextRequestGroups(const string& path);
+};
+
+typedef SharedHandle<MetalinkPostDownloadHandler> MetalinkPostDownloadHandlerHandle;
+#endif // _D_METALINK_POST_DOWNLOAD_HANDLER_H_
diff --git a/src/MultiDiskAdaptor.cc b/src/MultiDiskAdaptor.cc
index b866d68e..a57ea5dc 100644
--- a/src/MultiDiskAdaptor.cc
+++ b/src/MultiDiskAdaptor.cc
@@ -34,17 +34,19 @@
/* copyright --> */
#include "MultiDiskAdaptor.h"
#include "DefaultDiskWriter.h"
-#include "DlAbortEx.h"
#include "message.h"
#include "Util.h"
+#include "MultiFileAllocationIterator.h"
+#include "DefaultDiskWriterFactory.h"
-void MultiDiskAdaptor::resetDiskWriterEntries() {
+void MultiDiskAdaptor::resetDiskWriterEntries()
+{
diskWriterEntries.clear();
for(FileEntries::const_iterator itr = fileEntries.begin();
itr != fileEntries.end(); itr++) {
DiskWriterEntryHandle entry = new DiskWriterEntry(*itr);
if((*itr)->isRequested()) {
- entry->setDiskWriter(DefaultDiskWriter::createNewDiskWriter(option));
+ entry->setDiskWriter(DefaultDiskWriterFactory().newDiskWriter());
} else {
entry->setDiskWriter(new DefaultDiskWriter());
}
@@ -52,18 +54,23 @@ void MultiDiskAdaptor::resetDiskWriterEntries() {
}
}
-string MultiDiskAdaptor::getTopDirPath() const {
+string MultiDiskAdaptor::getTopDirPath() const
+{
return storeDir+"/"+topDir;
}
-void MultiDiskAdaptor::mkdir() const {
+void MultiDiskAdaptor::mkdir() const
+ throw(DlAbortEx*)
+{
for(FileEntries::const_iterator itr = fileEntries.begin();
itr != fileEntries.end(); itr++) {
(*itr)->setupDir(getTopDirPath());
}
}
-void MultiDiskAdaptor::openFile() {
+void MultiDiskAdaptor::openFile()
+ throw(DlAbortEx*)
+{
mkdir();
resetDiskWriterEntries();
for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
@@ -72,7 +79,9 @@ void MultiDiskAdaptor::openFile() {
}
}
-void MultiDiskAdaptor::initAndOpenFile() {
+void MultiDiskAdaptor::initAndOpenFile()
+ throw(DlAbortEx*)
+{
mkdir();
resetDiskWriterEntries();
for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
@@ -81,7 +90,9 @@ void MultiDiskAdaptor::initAndOpenFile() {
}
}
-void MultiDiskAdaptor::openExistingFile() {
+void MultiDiskAdaptor::openExistingFile()
+ throw(DlAbortEx*)
+{
resetDiskWriterEntries();
for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
itr != diskWriterEntries.end(); itr++) {
@@ -89,20 +100,24 @@ void MultiDiskAdaptor::openExistingFile() {
}
}
-void MultiDiskAdaptor::closeFile() {
+void MultiDiskAdaptor::closeFile()
+{
for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
itr != diskWriterEntries.end(); itr++) {
(*itr)->closeFile();
}
}
-void MultiDiskAdaptor::onDownloadComplete() {
+void MultiDiskAdaptor::onDownloadComplete()
+ throw(DlAbortEx*)
+{
closeFile();
openFile();
}
void MultiDiskAdaptor::writeData(const unsigned char* data, int32_t len,
int64_t offset)
+ throw(DlAbortEx*)
{
int64_t fileOffset = offset;
bool writing = false;
@@ -145,6 +160,7 @@ 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;
@@ -184,6 +200,7 @@ 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();
@@ -192,3 +209,8 @@ int64_t MultiDiskAdaptor::size() const
}
return size;
}
+
+FileAllocationIteratorHandle MultiDiskAdaptor::fileAllocationIterator()
+{
+ return new MultiFileAllocationIterator(this);
+}
diff --git a/src/MultiDiskAdaptor.h b/src/MultiDiskAdaptor.h
index 1d01d937..8e1b8424 100644
--- a/src/MultiDiskAdaptor.h
+++ b/src/MultiDiskAdaptor.h
@@ -39,6 +39,7 @@
#include "Option.h"
#include "DiskWriter.h"
#include "File.h"
+#include "DlAbortEx.h"
class DiskWriterEntry {
private:
@@ -57,16 +58,19 @@ 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());
}
@@ -82,6 +86,7 @@ public:
}
int64_t size() const
+ throw(DlAbortEx*)
{
return diskWriter->size();
}
@@ -112,7 +117,7 @@ private:
void resetDiskWriterEntries();
- void mkdir() const;
+ void mkdir() const throw(DlAbortEx*);
bool isInRange(const DiskWriterEntryHandle entry, int64_t offset) const;
@@ -128,28 +133,31 @@ public:
virtual ~MultiDiskAdaptor() {}
- virtual void initAndOpenFile();
+ virtual void initAndOpenFile() throw(DlAbortEx*);
- virtual void openFile();
+ virtual void openFile() throw(DlAbortEx*);
- virtual void openExistingFile();
+ virtual void openExistingFile() throw(DlAbortEx*);
virtual void closeFile();
- virtual void onDownloadComplete();
+ virtual void onDownloadComplete() throw(DlAbortEx*);
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 string getFilePath() {
+ virtual string getFilePath()
+ {
return getTopDirPath();
}
- virtual int64_t size() const;
+ virtual int64_t size() const throw(DlAbortEx*);
+
+ virtual FileAllocationIteratorHandle fileAllocationIterator();
void setTopDir(const string& topDir) {
this->topDir = topDir;
diff --git a/src/MultiDiskWriter.cc b/src/MultiDiskWriter.cc
deleted file mode 100644
index 89ae72bf..00000000
--- a/src/MultiDiskWriter.cc
+++ /dev/null
@@ -1,214 +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 "MultiDiskWriter.h"
-#include "DlAbortEx.h"
-#include "Util.h"
-#include "message.h"
-#include <errno.h>
-
-MultiDiskWriter::MultiDiskWriter(int pieceLength):
- pieceLength(pieceLength),
- ctx(DIGEST_ALGO_SHA1),
- fileAllocator(0) {
- ctx.digestInit();
-}
-
-MultiDiskWriter::~MultiDiskWriter() {
- clearEntries();
-}
-
-void MultiDiskWriter::clearEntries() {
- for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
- itr != diskWriterEntries.end(); itr++) {
- delete *itr;
- }
- diskWriterEntries.clear();
-}
-
-void MultiDiskWriter::setFileEntries(const FileEntries& fileEntries) {
- clearEntries();
- for(FileEntries::const_iterator itr = fileEntries.begin();
- itr != fileEntries.end(); itr++) {
- diskWriterEntries.push_back(new DiskWriterEntry(*itr));
- }
-}
-
-void MultiDiskWriter::configureFileAllocator(DiskWriterEntry* entry) {
- if(entry->fileEntry->isRequested()) {
- entry->diskWriter->setFileAllocator(fileAllocator);
- } else {
- entry->diskWriter->setFileAllocator(0);
- }
-}
-
-void MultiDiskWriter::openFile(const string& filename) {
- for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
- itr != diskWriterEntries.end(); itr++) {
- configureFileAllocator(*itr);
- (*itr)->diskWriter->openFile(filename+"/"+(*itr)->fileEntry->getPath());
- }
-}
-
-// filename is a directory which is specified by the user in the option.
-void MultiDiskWriter::initAndOpenFile(const string& filename) {
- for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
- itr != diskWriterEntries.end(); itr++) {
- configureFileAllocator(*itr);
- (*itr)->diskWriter->initAndOpenFile(filename+"/"+(*itr)->fileEntry->getPath());
- }
-}
-
-void MultiDiskWriter::closeFile() {
- for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
- itr != diskWriterEntries.end(); itr++) {
- (*itr)->diskWriter->closeFile();
- }
-}
-
-void MultiDiskWriter::openExistingFile(const string& filename) {
- for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
- itr != diskWriterEntries.end(); itr++) {
- (*itr)->diskWriter->setFileAllocator(0);
- (*itr)->diskWriter->openExistingFile(filename+"/"+(*itr)->fileEntry->getPath());
- }
-}
-
-void MultiDiskWriter::writeData(const char* data, int len, long long int offset) {
- long long int fileOffset = offset;
- bool writing = false;
- int rem = len;
- for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
- itr != diskWriterEntries.end() && rem != 0; itr++) {
- if(isInRange(*itr, offset) || writing) {
- int writeLength = calculateLength(*itr, fileOffset, rem);
- (*itr)->diskWriter->writeData(data+(len-rem), writeLength, fileOffset);
- rem -= writeLength;
- writing = true;
- fileOffset = 0;
- } else {
- fileOffset -= (*itr)->fileEntry->getLength();
- }
- }
- if(!writing) {
- throw new DlAbortEx(EX_FILE_OFFSET_OUT_OF_RANGE, offset);
- }
-}
-
-bool MultiDiskWriter::isInRange(const DiskWriterEntry* entry, long long int offset) const {
- return entry->fileEntry->getOffset() <= offset &&
- offset < entry->fileEntry->getOffset()+entry->fileEntry->getLength();
-}
-
-int MultiDiskWriter::calculateLength(const DiskWriterEntry* entry, long long int fileOffset, int rem) const {
- int length;
- if(entry->fileEntry->getLength() < fileOffset+rem) {
- length = entry->fileEntry->getLength()-fileOffset;
- } else {
- length = rem;
- }
- return length;
-}
-
-int MultiDiskWriter::readData(char* data, int len, long long int offset) {
- long long int fileOffset = offset;
- bool reading = false;
- int rem = len;
- int totalReadLength = 0;
- for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
- itr != diskWriterEntries.end() && rem != 0; itr++) {
- if(isInRange(*itr, offset) || reading) {
- int readLength = calculateLength((*itr), fileOffset, rem);
- totalReadLength += (*itr)->diskWriter->readData(data+(len-rem), readLength, fileOffset);
- rem -= readLength;
- reading = true;
- fileOffset = 0;
- } else {
- fileOffset -= (*itr)->fileEntry->getLength();
- }
- }
- if(!reading) {
- throw new DlAbortEx(EX_FILE_OFFSET_OUT_OF_RANGE, offset);
- }
- return totalReadLength;
-}
-
-void MultiDiskWriter::hashUpdate(DiskWriterEntry* entry, long long int offset, long long int length) {
- int BUFSIZE = 16*1024;
- char buf[BUFSIZE];
- for(int i = 0; i < length/BUFSIZE; i++) {
- if(BUFSIZE != entry->diskWriter->readData(buf, BUFSIZE, offset)) {
- throw string("error");
- }
- ctx.digestUpdate(buf, BUFSIZE);
- offset += BUFSIZE;
- }
- int r = length%BUFSIZE;
- if(r > 0) {
- if(r != entry->diskWriter->readData(buf, r, offset)) {
- throw string("error");
- }
- ctx.digestUpdate(buf, r);
- }
-}
-
-string MultiDiskWriter::sha1Sum(long long int offset, long long int length) {
- long long int fileOffset = offset;
- bool reading = false;
- int rem = length;
- ctx.digestReset();
- try {
- for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
- itr != diskWriterEntries.end() && rem != 0; itr++) {
- if(isInRange(*itr, offset) || reading) {
- int readLength = calculateLength((*itr), fileOffset, rem);
- hashUpdate(*itr, fileOffset, readLength);
- rem -= readLength;
- reading = true;
- fileOffset = 0;
- } else {
- fileOffset -= (*itr)->fileEntry->getLength();
- }
- }
- if(!reading) {
- throw new DlAbortEx(EX_FILE_OFFSET_OUT_OF_RANGE, offset);
- }
- unsigned char hashValue[20];
- ctx.digestFinal(hashValue);
- return Util::toHex(hashValue, 20);
- } catch(string ex) {
- throw new DlAbortEx(EX_FILE_SHA1SUM, "", strerror(errno));
- }
-}
-
diff --git a/src/MultiDiskWriter.h b/src/MultiDiskWriter.h
deleted file mode 100644
index 6fa229a2..00000000
--- a/src/MultiDiskWriter.h
+++ /dev/null
@@ -1,89 +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 --> */
-#ifndef _D_MULTI_DISK_WRITER_H_
-#define _D_MULTI_DISK_WRITER_H_
-
-#include "DefaultDiskWriter.h"
-#include "messageDigest.h"
-#include "FileEntry.h"
-#include "FileAllocator.h"
-
-class DiskWriterEntry {
-public:
- FileEntryHandle fileEntry;
- DefaultDiskWriter* diskWriter;
-public:
- DiskWriterEntry(const FileEntryHandle& fileEntry):fileEntry(fileEntry) {
- diskWriter = new DefaultDiskWriter(this->fileEntry->getLength());
- }
- ~DiskWriterEntry() {
- delete diskWriter;
- }
-};
-
-typedef deque<DiskWriterEntry*> DiskWriterEntries;
-
-class MultiDiskWriter : public DiskWriter {
-private:
- DiskWriterEntries diskWriterEntries;
- int pieceLength;
- MessageDigestContext ctx;
- FileAllocatorHandle fileAllocator;
-
- bool isInRange(const DiskWriterEntry* entry, long long int offset) const;
- int calculateLength(const DiskWriterEntry* entry, long long int fileOffset, int rem) const;
- void clearEntries();
- void hashUpdate(DiskWriterEntry* entry, long long int offset, long long int length);
- void configureFileAllocator(DiskWriterEntry* entry);
-public:
- MultiDiskWriter(int pieceLength);
- virtual ~MultiDiskWriter();
-
- void setFileEntries(const FileEntries& fileEntries);
-
- virtual void openFile(const string& filename);
- virtual void initAndOpenFile(const string& filename);
- virtual void closeFile();
- virtual void openExistingFile(const string& filename);
- virtual void writeData(const char* data, int len, long long int position = 0);
- virtual int readData(char* data, int len, long long int position);
- virtual string sha1Sum(long long int offset, long long int length);
-
- void setFileAllocator(const FileAllocatorHandle& fileAllocator) {
- this->fileAllocator = fileAllocator;
- }
-};
-
-#endif // _D_MULTI_DISK_WRITER_H_
diff --git a/src/GlowFileAllocator.cc b/src/MultiFileAllocationIterator.cc
index 6a6f2334..fb2f7fe4 100644
--- a/src/GlowFileAllocator.cc
+++ b/src/MultiFileAllocationIterator.cc
@@ -32,44 +32,70 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
-#include "GlowFileAllocator.h"
-#include "DlAbortEx.h"
-#include "TimeA2.h"
-#include "a2io.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
+#include "MultiFileAllocationIterator.h"
+#include "MultiDiskAdaptor.h"
+#include "FileEntry.h"
-void GlowFileAllocator::allocate(int fd, int64_t totalLength)
+#define BUFSIZE 16*1024
+
+MultiFileAllocationIterator::MultiFileAllocationIterator(MultiDiskAdaptor* diskAdaptor):
+ _diskAdaptor(diskAdaptor),
+ _entries(diskAdaptor->getFileEntries()),
+ _currentEntry(0),
+ _offset(0)
+{}
+
+MultiFileAllocationIterator::~MultiFileAllocationIterator() {}
+
+void MultiFileAllocationIterator::prepareNextEntry()
+{
+ _currentEntry = 0;
+ _offset = 0;
+ while(!_entries.empty()) {
+ FileEntryHandle entry = _entries.front();
+ _entries.pop_front();
+ if(entry->isRequested()) {
+ _currentEntry = entry;
+ _offset = File(_diskAdaptor->getStoreDir()+"/"+
+ _diskAdaptor->getTopDir()+"/"+
+ _currentEntry->getPath()).size();
+ break;
+ }
+ }
+}
+
+
+void MultiFileAllocationIterator::allocateChunk()
{
- struct stat fs;
- if(fstat(fd, &fs) < 0) {
- throw new DlAbortEx("fstat filed: %s", strerror(errno));
+ while(_currentEntry.isNull() || _currentEntry->getLength() <= _offset) {
+ prepareNextEntry();
+ if(_currentEntry.isNull()) {
+ break;
+ }
}
- if(fs.st_size != lseek(fd, 0, SEEK_END)) {
- throw new DlAbortEx("Seek failed: %s", strerror(errno));
+ if(finished()) {
+ return;
}
- int32_t bufSize = 4096;
- char buf[4096];
+ int32_t bufSize = BUFSIZE;
+ unsigned char buf[BUFSIZE];
memset(buf, 0, bufSize);
- int64_t x = (totalLength-fs.st_size+bufSize-1)/bufSize;
- fileAllocationMonitor->setMinValue(0);
- fileAllocationMonitor->setMaxValue(totalLength);
- fileAllocationMonitor->setCurrentValue(fs.st_size);
- fileAllocationMonitor->showProgress();
- Time cp;
- for(int64_t i = 0; i < x; ++i) {
- if(write(fd, buf, bufSize) < 0) {
- throw new DlAbortEx("Allocation failed: %s", strerror(errno));
- }
- if(cp.elapsedInMillis(500)) {
- fileAllocationMonitor->setCurrentValue(i*bufSize);
- fileAllocationMonitor->showProgress();
- cp.reset();
- }
+
+ int32_t wsize = _offset+bufSize > _currentEntry->getLength() ?
+ _currentEntry->getLength()-_offset:bufSize;
+ _diskAdaptor->writeData(buf, wsize, _offset+_currentEntry->getOffset());
+ _offset += wsize;
+}
+
+bool MultiFileAllocationIterator::finished()
+{
+ return _entries.empty() && _currentEntry.isNull();
+}
+
+int64_t MultiFileAllocationIterator::getTotalLength()
+{
+ if(_currentEntry.isNull()) {
+ return 0;
+ } else {
+ return _currentEntry->getLength();
}
- fileAllocationMonitor->setCurrentValue(totalLength);
- fileAllocationMonitor->showProgress();
- ftruncate(fd, totalLength);
}
diff --git a/src/FileAllocationMonitor.h b/src/MultiFileAllocationIterator.h
index 8d9c8354..6f97723e 100644
--- a/src/FileAllocationMonitor.h
+++ b/src/MultiFileAllocationIterator.h
@@ -32,36 +32,42 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
-#ifndef _D_FILE_ALLOCATION_MONITOR_H_
-#define _D_FILE_ALLOCATION_MONITOR_H_
+#ifndef _D_MULTI_FILE_ALLOCATION_ITERATOR_H_
+#define _D_MULTI_FILE_ALLOCATION_ITERATOR_H_
-#include "FileProgressMonitor.h"
+#include "FileAllocationIterator.h"
-typedef FileProgressMonitor<int64_t> FileAllocationMonitor;
-typedef SharedHandle<FileAllocationMonitor> FileAllocationMonitorHandle;
+class MultiDiskAdaptor;
+class FileEntry;
+extern typedef SharedHandle<FileEntry> FileEntryHandle;
+extern typedef deque<FileEntryHandle> FileEntries;
-class FileAllocationMonitorFactory;
-
-typedef SharedHandle<FileAllocationMonitorFactory> FileAllocationMonitorFactoryHandle;
-
-class FileAllocationMonitorFactory {
+class MultiFileAllocationIterator:public FileAllocationIterator
+{
private:
- static FileAllocationMonitorFactoryHandle factory;
-
-protected:
- FileAllocationMonitorFactory() {}
+ MultiDiskAdaptor* _diskAdaptor;
+ FileEntries _entries;
+ FileEntryHandle _currentEntry;
+ int64_t _offset;
public:
- static FileAllocationMonitorFactoryHandle getFactory() {
- return factory;
- }
+ MultiFileAllocationIterator(MultiDiskAdaptor* diskAdaptor);
- virtual ~FileAllocationMonitorFactory() {}
+ virtual ~MultiFileAllocationIterator();
- static void setFactory(const FileAllocationMonitorFactoryHandle& factory) {
- FileAllocationMonitorFactory::factory = factory;
+ void prepareNextEntry();
+
+ virtual void allocateChunk();
+
+ virtual bool finished();
+
+ virtual int64_t getCurrentLength()
+ {
+ return _offset;
}
- virtual FileAllocationMonitorHandle createNewMonitor() = 0;
+ virtual int64_t getTotalLength();
};
-#endif // _D_FILE_ALLOCATION_MONITOR_H_
+typedef SharedHandle<MultiFileAllocationIterator> MultiFileAllocationIteratorHandle;
+
+#endif // _D_MULTI_FILE_ALLOCATION_ITERATOR_H_
diff --git a/src/MultiUrlRequestInfo.cc b/src/MultiUrlRequestInfo.cc
index 99a08f17..6f7965c4 100644
--- a/src/MultiUrlRequestInfo.cc
+++ b/src/MultiUrlRequestInfo.cc
@@ -33,50 +33,56 @@
*/
/* copyright --> */
#include "MultiUrlRequestInfo.h"
+#include "RequestGroupMan.h"
+#include "DownloadEngine.h"
+#include "LogFactory.h"
+#include "RequestGroup.h"
#include "prefs.h"
#include "DownloadEngineFactory.h"
#include "RecoverableException.h"
#include "message.h"
#include "DNSCache.h"
-#include "TorrentRequestInfo.h"
-#include "MetalinkRequestInfo.h"
#include "Util.h"
+#include "ConsoleStatCalc.h"
#include <signal.h>
-extern volatile sig_atomic_t haltRequested;
+#ifndef SA_RESETHAND
+# define SA_RESETHAND 0x80000000
+#endif // SA_RESETHAND
-RequestInfoHandle MultiUrlRequestInfo::createNextRequestInfo(const string& filename) const
-{
-#ifdef ENABLE_BITTORRENT
- if(op->getAsBool(PREF_FOLLOW_TORRENT) &&
- Util::endsWith(filename, ".torrent")) {
- return new TorrentRequestInfo(filename, op);
- } else
-#endif // ENABLE_BITTORRENT
-#ifdef ENABLE_METALINK
- if(op->getAsBool(PREF_FOLLOW_METALINK) &&
- Util::endsWith(filename, ".metalink")) {
- return new MetalinkRequestInfo(filename, op);
- } else
-#endif // ENABLE_METALINK
- {
- return 0;
- }
-}
+extern volatile sig_atomic_t globalHaltRequested;
static void handler(int signal) {
- haltRequested = true;
+ globalHaltRequested = true;
+}
+
+MultiUrlRequestInfo::MultiUrlRequestInfo(const RequestGroups& requestGroups, Option* op):
+ _requestGroups(requestGroups),
+ _option(op),
+ _logger(LogFactory::getInstance())
+{}
+
+MultiUrlRequestInfo::~MultiUrlRequestInfo() {}
+
+void MultiUrlRequestInfo::printDownloadAbortMessage()
+{
+ printf(_("\nSome downloads were not complete because of errors."
+ " Check the log.\n"
+ "aria2 will resume download if the transfer is restarted."));
+ printf("\n");
}
-RequestInfos MultiUrlRequestInfo::execute() {
+void MultiUrlRequestInfo::execute()
+{
{
DNSCacheHandle dnsCache = new SimpleDNSCache();
DNSCacheSingletonHolder::instance(dnsCache);
}
- RequestInfos nextReqInfos;
try {
- SharedHandle<ConsoleDownloadEngine> e(DownloadEngineFactory::newConsoleEngine(op, _requestGroups));
+ DownloadEngineHandle e =
+ DownloadEngineFactory().newDownloadEngine(_option, _requestGroups);
+ e->setStatCalc(new ConsoleStatCalc());
e->fillCommand();
@@ -87,35 +93,21 @@ RequestInfos MultiUrlRequestInfo::execute() {
// This is done every 1 second. At the same time, it removes finished/error
// RequestGroup from DownloadEngine.
- Util::setGlobalSignalHandler(SIGINT, handler, 0);
- Util::setGlobalSignalHandler(SIGTERM, handler, 0);
+ Util::setGlobalSignalHandler(SIGINT, handler, SA_RESETHAND);
+ Util::setGlobalSignalHandler(SIGTERM, handler, SA_RESETHAND);
e->run();
- for(RequestGroups::iterator itr = _requestGroups.begin();
- itr != _requestGroups.end(); ++itr) {
- if((*itr)->downloadFinished()) {
- RequestInfoHandle reqInfo = createNextRequestInfo((*itr)->getFilePath());
- if(!reqInfo.isNull()) {
- nextReqInfos.push_back(reqInfo);
- }
- }
- }
- RequestGroupMan rgman(_requestGroups);
- // TODO print summary of the download result
- rgman.showDownloadResults(cout);
+ e->_requestGroupMan->showDownloadResults(cout);
cout << flush;
- // TODO Do we have to print a message when some of the downloads are failed?
- if(!rgman.downloadFinished()) {
+
+ if(!e->_requestGroupMan->downloadFinished()) {
printDownloadAbortMessage();
}
} catch(RecoverableException *ex) {
- logger->error(EX_EXCEPTION_CAUGHT, ex);
+ _logger->error(EX_EXCEPTION_CAUGHT, ex);
delete ex;
- fail = true;
}
Util::setGlobalSignalHandler(SIGINT, SIG_DFL, 0);
Util::setGlobalSignalHandler(SIGTERM, SIG_DFL, 0);
-
- return nextReqInfos;
}
diff --git a/src/MultiUrlRequestInfo.h b/src/MultiUrlRequestInfo.h
index de065a43..c7f7916d 100644
--- a/src/MultiUrlRequestInfo.h
+++ b/src/MultiUrlRequestInfo.h
@@ -35,27 +35,30 @@
#ifndef _D_MULTI_URL_REQUEST_INFO_H_
#define _D_MULTI_URL_REQUEST_INFO_H_
-#include "RequestInfo.h"
-#include "RequestGroup.h"
+#include "common.h"
-class MultiUrlRequestInfo : public RequestInfo {
+class RequestGroup;
+extern typedef SharedHandle<RequestGroup> RequestGroupHandle;
+extern typedef deque<RequestGroupHandle> RequestGroups;
+class Option;
+class Logger;
+
+class MultiUrlRequestInfo {
private:
RequestGroups _requestGroups;
- RequestInfoHandle createNextRequestInfo(const string& filename) const;
-public:
- MultiUrlRequestInfo(const RequestGroups& requestGroups, Option* op):
- RequestInfo(op),
- _requestGroups(requestGroups) {}
+ Option* _option;
- MultiUrlRequestInfo(const Strings& uris, Option* op):RequestInfo(op)
- {
- _requestGroups.push_back(new RequestGroup(uris, op));
- }
+ const Logger* _logger;
- virtual ~MultiUrlRequestInfo() {}
+ void printDownloadAbortMessage();
+
+public:
+ MultiUrlRequestInfo(const RequestGroups& requestGroups, Option* op);
+
+ virtual ~MultiUrlRequestInfo();
- virtual RequestInfos execute();
+ void execute();
};
typedef SharedHandle<MultiUrlRequestInfo> MultiUrlRequestInfoHandle;
diff --git a/src/NullProgressInfoFile.h b/src/NullProgressInfoFile.h
new file mode 100644
index 00000000..7fd8415c
--- /dev/null
+++ b/src/NullProgressInfoFile.h
@@ -0,0 +1,60 @@
+/* <!-- 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_NULL_PROGRESS_INFO_FILE_H_
+#define _D_NULL_PROGRESS_INFO_FILE_H_
+
+#include "BtProgressInfoFile.h"
+
+class NullProgressInfoFile:public BtProgressInfoFile {
+public:
+ virtual ~NullProgressInfoFile() {}
+
+ virtual string getFilename()
+ {
+ return "";
+ }
+
+ virtual bool exists() { return false; }
+
+ virtual void save() {}
+
+ virtual void load() {}
+
+ virtual void removeFile() {}
+};
+
+typedef SharedHandle<NullProgressInfoFile> NullProgressInfoFileHandle;
+
+#endif // _D_NULL_PROGRESS_INFO_FILE_H_
diff --git a/src/Peer.cc b/src/Peer.cc
index 1017c250..44ef73f6 100644
--- a/src/Peer.cc
+++ b/src/Peer.cc
@@ -54,6 +54,14 @@ Peer::Peer(string ipaddr, int32_t port, int32_t pieceLength, int64_t totalLength
id = MessageDigestHelper::digestString("sha1", idSeed);
}
+void Peer::reconfigure(int32_t pieceLength, int64_t totalLength)
+{
+ delete bitfield;
+ this->pieceLength = pieceLength;
+ this->bitfield = BitfieldManFactory::getFactoryInstance()->
+ createBitfieldMan(this->pieceLength, totalLength);
+}
+
/*
Peer::Peer():entryId(0), ipaddr(""), port(0), bitfield(0),
sessionUploadLength(0), sessionDownloadLength(0),
diff --git a/src/Peer.h b/src/Peer.h
index 63b5f07c..2fbbdc6d 100644
--- a/src/Peer.h
+++ b/src/Peer.h
@@ -210,6 +210,8 @@ public:
void startBadCondition();
bool isGood() const;
+
+ void reconfigure(int32_t pieceLength, int64_t totalLength);
};
typedef SharedHandle<Peer> PeerHandle;
diff --git a/src/PeerAbstractCommand.cc b/src/PeerAbstractCommand.cc
index 86c44338..4454a519 100644
--- a/src/PeerAbstractCommand.cc
+++ b/src/PeerAbstractCommand.cc
@@ -33,33 +33,34 @@
*/
/* copyright --> */
#include "PeerAbstractCommand.h"
+#include "Peer.h"
+#include "DownloadEngine.h"
+#include "Option.h"
#include "DlAbortEx.h"
#include "DlRetryEx.h"
#include "Util.h"
#include "message.h"
#include "prefs.h"
-PeerAbstractCommand::PeerAbstractCommand(int32_t cuid, const PeerHandle& peer,
- TorrentDownloadEngine* e,
- const BtContextHandle& btContext,
+PeerAbstractCommand::PeerAbstractCommand(int32_t cuid,
+ const PeerHandle& peer,
+ DownloadEngine* e,
const SocketHandle& s)
- :BtContextAwareCommand(cuid, btContext), e(e), socket(s), peer(peer),
+ :Command(cuid), e(e), socket(s), peer(peer),
checkSocketIsReadable(false), checkSocketIsWritable(false),
uploadLimitCheck(false), uploadLimit(0), noCheck(false)
{
setReadCheckSocket(socket);
timeout = e->option->getAsInt(PREF_BT_TIMEOUT);
- btRuntime->increaseConnections();
}
PeerAbstractCommand::~PeerAbstractCommand() {
disableReadCheckSocket();
disableWriteCheckSocket();
- btRuntime->decreaseConnections();
}
bool PeerAbstractCommand::execute() {
- if(btRuntime->isHalt()) {
+ if(exitBeforeExecute()) {
peer->resetStatus();
return true;
}
@@ -96,10 +97,6 @@ bool PeerAbstractCommand::prepareForRetry(int32_t wait) {
return true;
}
-void PeerAbstractCommand::onAbort(Exception* ex) {
- peerStorage->returnPeer(peer);
-}
-
void PeerAbstractCommand::disableReadCheckSocket() {
if(checkSocketIsReadable) {
e->deleteSocketForReadCheck(readCheckTarget, this);
diff --git a/src/PeerAbstractCommand.h b/src/PeerAbstractCommand.h
index e50aabde..79a4d030 100644
--- a/src/PeerAbstractCommand.h
+++ b/src/PeerAbstractCommand.h
@@ -35,25 +35,29 @@
#ifndef _D_PEER_ABSTRACT_COMMAND_H_
#define _D_PEER_ABSTRACT_COMMAND_H_
-#include "BtContextAwareCommand.h"
-#include "Request.h"
-#include "TorrentDownloadEngine.h"
+#include "Command.h"
#include "TimeA2.h"
-#include "Exception.h"
+#include "Socket.h"
-class PeerAbstractCommand : public BtContextAwareCommand {
+class DownloadEngine;
+class Exception;
+class Peer;
+extern typedef SharedHandle<Peer> PeerHandle;
+
+class PeerAbstractCommand : public Command {
private:
Time checkPoint;
int32_t timeout;
protected:
- TorrentDownloadEngine* e;
+ DownloadEngine* e;
SocketHandle socket;
PeerHandle peer;
void setTimeout(int32_t timeout) { this->timeout = timeout; }
virtual bool prepareForNextPeer(int32_t wait);
virtual bool prepareForRetry(int32_t wait);
- virtual void onAbort(Exception* ex);
+ virtual void onAbort(Exception* ex) {};
+ virtual bool exitBeforeExecute() = 0;
virtual bool executeInternal() = 0;
void setReadCheckSocket(const SocketHandle& socket);
void setWriteCheckSocket(const SocketHandle& socket);
@@ -71,12 +75,13 @@ private:
int32_t uploadLimit;
bool noCheck;
public:
- PeerAbstractCommand(int32_t cuid, const PeerHandle& peer,
- TorrentDownloadEngine* e,
- const BtContextHandle& btContext,
+ PeerAbstractCommand(int32_t cuid,
+ const PeerHandle& peer,
+ DownloadEngine* e,
const SocketHandle& s = SocketHandle());
virtual ~PeerAbstractCommand();
- bool execute();
+
+ virtual bool execute();
};
#endif // _D_PEER_ABSTRACT_COMMAND_H_
diff --git a/src/PeerChokeCommand.cc b/src/PeerChokeCommand.cc
index de06502b..7c2eec0e 100644
--- a/src/PeerChokeCommand.cc
+++ b/src/PeerChokeCommand.cc
@@ -36,13 +36,17 @@
#include "Util.h"
PeerChokeCommand::PeerChokeCommand(int32_t cuid,
- TorrentDownloadEngine* e,
+ RequestGroup* requestGroup,
+ DownloadEngine* e,
const BtContextHandle& btContext,
int32_t interval):
- BtContextAwareCommand(cuid, btContext),
+ Command(cuid),
+ BtContextAwareCommand(btContext),
+ RequestGroupAware(requestGroup),
interval(interval),
e(e),
- rotate(0) {}
+ rotate(0)
+{}
PeerChokeCommand::~PeerChokeCommand() {}
diff --git a/src/PeerChokeCommand.h b/src/PeerChokeCommand.h
index 687f405c..0a2b2f67 100644
--- a/src/PeerChokeCommand.h
+++ b/src/PeerChokeCommand.h
@@ -35,14 +35,19 @@
#ifndef _D_PEER_CHOKE_COMMAND_H_
#define _D_PEER_CHOKE_COMMAND_H_
+#include "Command.h"
#include "BtContextAwareCommand.h"
-#include "TorrentDownloadEngine.h"
+#include "DownloadEngine.h"
#include "TimeA2.h"
+#include "RequestGroupAware.h"
-class PeerChokeCommand : public BtContextAwareCommand {
+class PeerChokeCommand : public Command,
+ public BtContextAwareCommand,
+ public RequestGroupAware
+{
private:
int32_t interval;
- TorrentDownloadEngine* e;
+ DownloadEngine* e;
int32_t rotate;
Time checkPoint;
@@ -52,13 +57,14 @@ private:
public:
PeerChokeCommand(int32_t cuid,
- TorrentDownloadEngine* e,
+ RequestGroup* requestGroup,
+ DownloadEngine* e,
const BtContextHandle& btContext,
int32_t interval);
virtual ~PeerChokeCommand();
- bool execute();
+ virtual bool execute();
};
#endif // _D_PEER_CHOKE_COMMAND_H_
diff --git a/src/PeerConnection.cc b/src/PeerConnection.cc
index fd231997..e62e1e25 100644
--- a/src/PeerConnection.cc
+++ b/src/PeerConnection.cc
@@ -122,17 +122,20 @@ bool PeerConnection::receiveMessage(unsigned char* data, int32_t& dataLength) {
return true;
}
-bool PeerConnection::receiveHandshake(unsigned char* data, int32_t& dataLength) {
- if(!socket->isReadable(0)) {
+bool PeerConnection::receiveHandshake(unsigned char* data, int32_t& dataLength,
+ bool peek) {
+ int32_t remain = BtHandshakeMessage::MESSAGE_LENGTH-resbufLength;
+ if(remain != 0 && !socket->isReadable(0)) {
dataLength = 0;
return false;
}
- int32_t remain = BtHandshakeMessage::MESSAGE_LENGTH-resbufLength;
int32_t temp = remain;
- socket->readData((char*)resbuf+resbufLength, temp);
- if(temp == 0) {
- // we got EOF
- throw new DlAbortEx(EX_EOF_FROM_PEER);
+ if(remain != 0) {
+ socket->readData((char*)resbuf+resbufLength, temp);
+ if(temp == 0) {
+ // we got EOF
+ throw new DlAbortEx(EX_EOF_FROM_PEER);
+ }
}
bool retval;
if(remain != temp) {
@@ -141,11 +144,11 @@ bool PeerConnection::receiveHandshake(unsigned char* data, int32_t& dataLength)
retval = true;
}
resbufLength += temp;
- // we got whole handshake payload
+
int32_t writeLength = resbufLength > dataLength ? dataLength : resbufLength;
memcpy(data, resbuf, writeLength);
dataLength = writeLength;
- if(retval) {
+ if(retval && !peek) {
resbufLength = 0;
}
return retval;
diff --git a/src/PeerConnection.h b/src/PeerConnection.h
index 3e941ae5..6cf5dbf2 100644
--- a/src/PeerConnection.h
+++ b/src/PeerConnection.h
@@ -72,7 +72,7 @@ public:
* In both cases, 'msg' is filled with received bytes and the filled length
* is assigned to 'length'.
*/
- bool receiveHandshake(unsigned char* data, int32_t& dataLength);
+ bool receiveHandshake(unsigned char* data, int32_t& dataLength, bool peek = false);
};
typedef SharedHandle<PeerConnection> PeerConnectionHandle;
diff --git a/src/PeerInitiateConnectionCommand.cc b/src/PeerInitiateConnectionCommand.cc
index 8ada7e3f..8139f1fe 100644
--- a/src/PeerInitiateConnectionCommand.cc
+++ b/src/PeerInitiateConnectionCommand.cc
@@ -33,6 +33,7 @@
*/
/* copyright --> */
#include "PeerInitiateConnectionCommand.h"
+#include "DownloadEngine.h"
#include "PeerInteractionCommand.h"
#include "Util.h"
#include "DlAbortEx.h"
@@ -41,12 +42,21 @@
#include "CUIDCounter.h"
PeerInitiateConnectionCommand::PeerInitiateConnectionCommand(int cuid,
+ RequestGroup* requestGroup,
const PeerHandle& peer,
- TorrentDownloadEngine* e,
+ DownloadEngine* e,
const BtContextHandle& btContext)
- :PeerAbstractCommand(cuid, peer, e, btContext) {}
+ :PeerAbstractCommand(cuid, peer, e),
+ BtContextAwareCommand(btContext),
+ RequestGroupAware(requestGroup)
+{
+ btRuntime->increaseConnections();
+}
-PeerInitiateConnectionCommand::~PeerInitiateConnectionCommand() {}
+PeerInitiateConnectionCommand::~PeerInitiateConnectionCommand()
+{
+ btRuntime->decreaseConnections();
+}
bool PeerInitiateConnectionCommand::executeInternal() {
Command* command;
@@ -55,6 +65,7 @@ bool PeerInitiateConnectionCommand::executeInternal() {
socket->establishConnection(peer->ipaddr, peer->port);
command =
new PeerInteractionCommand(cuid,
+ _requestGroup,
peer,
e,
btContext,
@@ -72,6 +83,7 @@ bool PeerInitiateConnectionCommand::prepareForNextPeer(int wait) {
peer->cuid = CUIDCounterSingletonHolder::instance()->newID();
PeerInitiateConnectionCommand* command =
new PeerInitiateConnectionCommand(peer->cuid,
+ _requestGroup,
peer,
e,
btContext);
@@ -83,9 +95,19 @@ bool PeerInitiateConnectionCommand::prepareForNextPeer(int wait) {
bool PeerInitiateConnectionCommand::prepareForRetry(int wait) {
PeerInitiateConnectionCommand* command =
new PeerInitiateConnectionCommand(cuid,
+ _requestGroup,
peer,
e,
btContext);
e->commands.push_back(command);
return true;
}
+
+void PeerInitiateConnectionCommand::onAbort(Exception* ex) {
+ peerStorage->returnPeer(peer);
+}
+
+bool PeerInitiateConnectionCommand::exitBeforeExecute()
+{
+ return btRuntime->isHalt();
+}
diff --git a/src/PeerInitiateConnectionCommand.h b/src/PeerInitiateConnectionCommand.h
index 7a86f097..ee366ce6 100644
--- a/src/PeerInitiateConnectionCommand.h
+++ b/src/PeerInitiateConnectionCommand.h
@@ -36,19 +36,28 @@
#define _D_PEER_INITIATE_CONNECTION_H_
#include "PeerAbstractCommand.h"
+#include "RequestGroupAware.h"
+#include "BtContextAwareCommand.h"
-class PeerInitiateConnectionCommand : public PeerAbstractCommand {
+class PeerInitiateConnectionCommand : public PeerAbstractCommand,
+ public BtContextAwareCommand,
+ public RequestGroupAware
+{
protected:
- bool executeInternal();
- bool prepareForRetry(int wait);
- bool prepareForNextPeer(int wait);
+ virtual bool executeInternal();
+ virtual bool prepareForRetry(int wait);
+ virtual bool prepareForNextPeer(int wait);
+ virtual void onAbort(Exception* ex);
+ virtual bool exitBeforeExecute();
+
public:
PeerInitiateConnectionCommand(int cuid,
+ RequestGroup* requestGroup,
const PeerHandle& peer,
- TorrentDownloadEngine* e,
+ DownloadEngine* e,
const BtContextHandle& btContext);
- ~PeerInitiateConnectionCommand();
+ virtual ~PeerInitiateConnectionCommand();
};
#endif // _D_PEER_INITIATE_CONNECTION_H_
diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc
index 522b02ab..7d9794ac 100644
--- a/src/PeerInteractionCommand.cc
+++ b/src/PeerInteractionCommand.cc
@@ -33,6 +33,7 @@
*/
/* copyright --> */
#include "PeerInteractionCommand.h"
+#include "DownloadEngine.h"
#include "PeerInitiateConnectionCommand.h"
#include "PeerMessageUtil.h"
#include "DefaultBtInteractive.h"
@@ -45,17 +46,20 @@
#include "DefaultBtRequestFactory.h"
#include "DefaultBtMessageFactory.h"
#include "DefaultBtInteractive.h"
-#include "PeerConnection.h"
#include "CUIDCounter.h"
#include <algorithm>
PeerInteractionCommand::PeerInteractionCommand(int32_t cuid,
+ RequestGroup* requestGroup,
const PeerHandle& p,
- TorrentDownloadEngine* e,
+ DownloadEngine* e,
const BtContextHandle& btContext,
const SocketHandle& s,
- Seq sequence)
- :PeerAbstractCommand(cuid, p, e, btContext, s),
+ Seq sequence,
+ const PeerConnectionHandle& passedPeerConnection)
+ :PeerAbstractCommand(cuid, p, e, s),
+ BtContextAwareCommand(btContext),
+ RequestGroupAware(requestGroup),
sequence(sequence),
btInteractive(0),
maxDownloadSpeedLimit(0)
@@ -71,8 +75,8 @@ PeerInteractionCommand::PeerInteractionCommand(int32_t cuid,
factory->setBtContext(btContext);
factory->setPeer(peer);
- PeerConnectionHandle peerConnection =
- new PeerConnection(cuid, socket, e->option);
+ PeerConnectionHandle peerConnection = passedPeerConnection.isNull() ?
+ new PeerConnection(cuid, socket, e->option) : passedPeerConnection;
DefaultBtMessageDispatcherHandle dispatcher = new DefaultBtMessageDispatcher();
dispatcher->setCuid(cuid);
@@ -128,12 +132,15 @@ PeerInteractionCommand::PeerInteractionCommand(int32_t cuid,
peer->activate();
maxDownloadSpeedLimit = e->option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT);
+
+ btRuntime->increaseConnections();
}
PeerInteractionCommand::~PeerInteractionCommand() {
peer->deactivate();
PEER_OBJECT_CLUSTER(btContext)->unregisterHandle(peer->getId());
-
+
+ btRuntime->decreaseConnections();
//logger->debug("CUID#%d - unregistered message factory using ID:%s",
//cuid, peer->getId().c_str());
}
@@ -205,6 +212,7 @@ bool PeerInteractionCommand::prepareForNextPeer(int32_t wait) {
peer->cuid = CUIDCounterSingletonHolder::instance()->newID();
PeerInitiateConnectionCommand* command =
new PeerInitiateConnectionCommand(peer->cuid,
+ _requestGroup,
peer,
e,
btContext);
@@ -220,5 +228,12 @@ bool PeerInteractionCommand::prepareForRetry(int32_t wait) {
void PeerInteractionCommand::onAbort(Exception* ex) {
btInteractive->cancelAllPiece();
- PeerAbstractCommand::onAbort(ex);
+ peerStorage->returnPeer(peer);
+ //PeerAbstractCommand::onAbort(ex);
}
+
+bool PeerInteractionCommand::exitBeforeExecute()
+{
+ return btRuntime->isHalt();
+}
+
diff --git a/src/PeerInteractionCommand.h b/src/PeerInteractionCommand.h
index 0f999611..046504cc 100644
--- a/src/PeerInteractionCommand.h
+++ b/src/PeerInteractionCommand.h
@@ -36,9 +36,15 @@
#define _D_PEER_INTERACTION_COMMAND_H_
#include "PeerAbstractCommand.h"
+#include "RequestGroupAware.h"
+#include "BtContextAwareCommand.h"
#include "BtInteractive.h"
+#include "PeerConnection.h"
-class PeerInteractionCommand : public PeerAbstractCommand {
+class PeerInteractionCommand : public PeerAbstractCommand,
+ public BtContextAwareCommand,
+ public RequestGroupAware
+{
public:
enum Seq {
INITIATOR_SEND_HANDSHAKE,
@@ -55,13 +61,16 @@ protected:
virtual bool prepareForRetry(int32_t wait);
virtual bool prepareForNextPeer(int32_t wait);
virtual void onAbort(Exception* ex);
+ virtual bool exitBeforeExecute();
public:
PeerInteractionCommand(int32_t cuid,
+ RequestGroup* requestGroup,
const PeerHandle& peer,
- TorrentDownloadEngine* e,
+ DownloadEngine* e,
const BtContextHandle& btContext,
const SocketHandle& s,
- Seq sequence);
+ Seq sequence,
+ const PeerConnectionHandle& peerConnection = 0);
virtual ~PeerInteractionCommand();
diff --git a/src/PeerListenCommand.cc b/src/PeerListenCommand.cc
index e9e7b11c..f8162c40 100644
--- a/src/PeerListenCommand.cc
+++ b/src/PeerListenCommand.cc
@@ -33,17 +33,18 @@
*/
/* copyright --> */
#include "PeerListenCommand.h"
-#include "PeerInteractionCommand.h"
+#include "DownloadEngine.h"
+#include "Peer.h"
+#include "RequestGroupMan.h"
#include "RecoverableException.h"
#include "CUIDCounter.h"
#include "message.h"
+#include "PeerReceiveHandshakeCommand.h"
-PeerListenCommand::PeerListenCommand(int32_t cuid,
- TorrentDownloadEngine* e,
- const BtContextHandle& btContext)
- :BtContextAwareCommand(cuid, btContext),
- e(e),
- _lowestSpeedLimit(20*1024) {}
+PeerListenCommand::PeerListenCommand(int32_t cuid, DownloadEngine* e):
+ Command(cuid),
+ e(e),
+ _lowestSpeedLimit(20*1024) {}
PeerListenCommand::~PeerListenCommand() {}
@@ -68,7 +69,7 @@ int32_t PeerListenCommand::bindPort(int32_t portRangeStart, int32_t portRangeEnd
}
bool PeerListenCommand::execute() {
- if(btRuntime->isHalt()) {
+ if(e->isHaltRequested() || e->_requestGroupMan->countRequestGroup() == 0) {
return true;
}
for(int32_t i = 0; i < 3 && socket->isReadable(0); i++) {
@@ -80,24 +81,20 @@ bool PeerListenCommand::execute() {
pair<string, int32_t> localInfo;
peerSocket->getAddrInfo(localInfo);
- TransferStat tstat = peerStorage->calculateStat();
- if(peerInfo.first != localInfo.first &&
- (!pieceStorage->downloadFinished() && tstat.getDownloadSpeed() < _lowestSpeedLimit ||
- btRuntime->getConnections() < MAX_PEERS)) {
- PeerHandle peer = PeerHandle(new Peer(peerInfo.first, peerInfo.second,
- btContext->getPieceLength(),
- btContext->getTotalLength()));
- if(peerStorage->addIncomingPeer(peer)) {
- peer->cuid = CUIDCounterSingletonHolder::instance()->newID();
- PeerInteractionCommand* command =
- new PeerInteractionCommand(peer->cuid, peer, e,
- btContext,
- peerSocket,
- PeerInteractionCommand::RECEIVER_WAIT_HANDSHAKE);
- e->commands.push_back(command);
- logger->debug(MSG_INCOMING_PEER_CONNECTION, cuid, peer->cuid);
- }
+ if(peerInfo.first == localInfo.first) {
+ continue;
}
+ PeerHandle peer = new Peer(peerInfo.first, peerInfo.second, 0, 0);
+ PeerReceiveHandshakeCommand* command =
+ new PeerReceiveHandshakeCommand(CUIDCounterSingletonHolder::instance()->newID(),
+ peer, e, peerSocket);
+ e->commands.push_back(command);
+ logger->debug("Accepted the connection from %s:%d.",
+ peer->ipaddr.c_str(),
+ peer->port);
+ logger->debug("Added CUID#%d to receive Bt handshake.",
+ command->getCuid());
+
} catch(RecoverableException* ex) {
logger->debug(MSG_ACCEPT_FAILURE, ex, cuid);
delete ex;
diff --git a/src/PeerListenCommand.h b/src/PeerListenCommand.h
index e385da2d..5997dfee 100644
--- a/src/PeerListenCommand.h
+++ b/src/PeerListenCommand.h
@@ -35,22 +35,22 @@
#ifndef _D_PEER_LISTEN_COMMAND_H_
#define _D_PEER_LISTEN_COMMAND_H_
-#include "BtContextAwareCommand.h"
-#include "TorrentDownloadEngine.h"
+#include "Command.h"
+#include "Socket.h"
-class PeerListenCommand : public BtContextAwareCommand {
+class DownloadEngine;
+
+class PeerListenCommand : public Command {
private:
- TorrentDownloadEngine* e;
+ DownloadEngine* e;
SocketHandle socket;
int32_t _lowestSpeedLimit;
public:
- PeerListenCommand(int32_t cuid,
- TorrentDownloadEngine* e,
- const BtContextHandle& btContext);
+ PeerListenCommand(int32_t cuid, DownloadEngine* e);
virtual ~PeerListenCommand();
- bool execute();
+ virtual bool execute();
int32_t bindPort(int32_t portRangeStart, int32_t portRangeEnd);
diff --git a/src/PeerReceiveHandshakeCommand.cc b/src/PeerReceiveHandshakeCommand.cc
new file mode 100644
index 00000000..81d9fb72
--- /dev/null
+++ b/src/PeerReceiveHandshakeCommand.cc
@@ -0,0 +1,101 @@
+/* <!-- 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 "PeerReceiveHandshakeCommand.h"
+#include "PeerConnection.h"
+#include "DownloadEngine.h"
+#include "BtHandshakeMessage.h"
+#include "Util.h"
+#include "BtContext.h"
+#include "DlAbortEx.h"
+#include "PeerInteractionCommand.h"
+#include "message.h"
+
+PeerReceiveHandshakeCommand::PeerReceiveHandshakeCommand(int32_t cuid,
+ const PeerHandle& peer,
+ DownloadEngine* e,
+ const SocketHandle& s):
+ PeerAbstractCommand(cuid, peer, e, s),
+ _peerConnection(new PeerConnection(cuid, s, e->option)),
+ _lowestSpeedLimit(20*1024)
+{}
+
+PeerReceiveHandshakeCommand::~PeerReceiveHandshakeCommand() {}
+
+bool PeerReceiveHandshakeCommand::exitBeforeExecute()
+{
+ return e->isHaltRequested();
+}
+
+bool PeerReceiveHandshakeCommand::executeInternal()
+{
+ unsigned char data[BtHandshakeMessage::MESSAGE_LENGTH];
+ int32_t dataLength = BtHandshakeMessage::MESSAGE_LENGTH;
+ // ignore return value. The received data is kept in PeerConnection object
+ // because of peek = true.
+ _peerConnection->receiveHandshake(data, dataLength, true);
+ // To handle tracker's NAT-checking feature
+ if(dataLength >= 48) {
+ // check info_hash
+ string infoHash = Util::toHex(&data[28], INFO_HASH_LENGTH);
+ BtContextHandle btContext = BtRegistry::getBtContext(infoHash);
+ if(btContext.isNull() || !BT_RUNTIME(btContext)->ready()) {
+ throw new DlAbortEx("Unknown info hash %s", infoHash.c_str());
+ }
+ TransferStat tstat = PEER_STORAGE(btContext)->calculateStat();
+ if(!PIECE_STORAGE(btContext)->downloadFinished() && tstat.getDownloadSpeed() < _lowestSpeedLimit ||
+ BT_RUNTIME(btContext)->getConnections() < MAX_PEERS) {
+ peer->reconfigure(btContext->getPieceLength(), btContext->getTotalLength());
+ PEER_STORAGE(btContext)->addIncomingPeer(peer);
+
+ peer->cuid = cuid;
+
+ PeerInteractionCommand* command =
+ new PeerInteractionCommand(cuid,
+ btContext->getOwnerRequestGroup(),
+ peer,
+ e,
+ btContext,
+ socket,
+ PeerInteractionCommand::RECEIVER_WAIT_HANDSHAKE,
+ _peerConnection);
+ e->commands.push_back(command);
+ logger->debug(MSG_INCOMING_PEER_CONNECTION, cuid, peer->cuid);
+ }
+ return true;
+ } else {
+ e->commands.push_back(this);
+ return false;
+ }
+}
diff --git a/src/PeerReceiveHandshakeCommand.h b/src/PeerReceiveHandshakeCommand.h
new file mode 100644
index 00000000..26b907ad
--- /dev/null
+++ b/src/PeerReceiveHandshakeCommand.h
@@ -0,0 +1,68 @@
+/* <!-- 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_PEER_RECEIVE_HANDSHAKE_COMMAND_H_
+#define _D_PEER_RECEIVE_HANDSHAKE_COMMAND_H_
+
+#include "PeerAbstractCommand.h"
+
+class PeerConnection;
+extern typedef SharedHandle<PeerConnection> PeerConnectionHandle;
+
+class PeerReceiveHandshakeCommand:public PeerAbstractCommand
+{
+private:
+ PeerConnectionHandle _peerConnection;
+
+ int32_t _lowestSpeedLimit;
+
+protected:
+ virtual bool executeInternal();
+ /*
+ virtual bool prepareForRetry(int32_t wait);
+ virtual bool prepareForNextPeer(int32_t wait);
+ */
+ virtual bool exitBeforeExecute();
+public:
+ PeerReceiveHandshakeCommand(int32_t cuid,
+ const PeerHandle& peer,
+ DownloadEngine* e,
+ const SocketHandle& s);
+
+ virtual ~PeerReceiveHandshakeCommand();
+
+
+};
+
+#endif // _D_PEER_RECEIVE_HANDSHAKE_COMMAND_H_
diff --git a/src/PeerStorage.h b/src/PeerStorage.h
index 1b463936..a7e4accd 100644
--- a/src/PeerStorage.h
+++ b/src/PeerStorage.h
@@ -37,70 +37,7 @@
#include "common.h"
#include "Peer.h"
-
-class TransferStat {
-public:
- int32_t downloadSpeed;
- int32_t uploadSpeed;
- int64_t sessionDownloadLength;
- int64_t sessionUploadLength;
-
- void copy(const TransferStat& stat)
- {
- downloadSpeed = stat.downloadSpeed;
- uploadSpeed = stat.uploadSpeed;
- sessionDownloadLength = stat.sessionDownloadLength;
- sessionUploadLength = stat.sessionUploadLength;
- }
-public:
- TransferStat():downloadSpeed(0), uploadSpeed(0),
- sessionDownloadLength(0), sessionUploadLength(0) {}
-
- TransferStat(const TransferStat& stat)
- {
- copy(stat);
- }
-
- TransferStat& operator=(const TransferStat& stat)
- {
- if(this != &stat) {
- copy(stat);
- }
- return *this;
- }
-
- int32_t getDownloadSpeed() const {
- return downloadSpeed;
- }
-
- void setDownloadSpeed(int32_t s) { downloadSpeed = s; }
-
- int32_t getUploadSpeed() const {
- return uploadSpeed;
- }
-
- void setUploadSpeed(int32_t s) { uploadSpeed = s; }
-
- /**
- * Returns the number of bytes downloaded since the program started.
- * This is not the total number of bytes downloaded.
- */
- int64_t getSessionDownloadLength() const {
- return sessionDownloadLength;
- }
-
- void setSessionDownloadLength(int64_t s) { sessionDownloadLength = s; }
-
- /**
- * Returns the number of bytes uploaded since the program started.
- * This is not the total number of bytes uploaded.
- */
- int64_t getSessionUploadLength() const {
- return sessionUploadLength;
- }
-
- void setSessionUploadLength(int64_t s) { sessionUploadLength = s; }
-};
+#include "TransferStat.h"
class PeerStorage {
public:
diff --git a/src/Piece.cc b/src/Piece.cc
index e227bbaa..6aec598e 100644
--- a/src/Piece.cc
+++ b/src/Piece.cc
@@ -101,3 +101,16 @@ BlockIndexes Piece::getAllMissingBlockIndexes() const {
string Piece::toString() const {
return "piece: index="+Util::itos(index)+", length="+Util::itos(length);
}
+
+void Piece::reconfigure(int32_t length)
+{
+ this->length = length;
+ bitfield =
+ BitfieldManFactory::getFactoryInstance()->createBitfieldMan(BLOCK_LENGTH, length);
+}
+
+void Piece::setBitfield(const unsigned char* bitfield, int32_t len)
+{
+ this->bitfield->setBitfield(bitfield, len);
+}
+
diff --git a/src/Piece.h b/src/Piece.h
index 8b779560..f9f04788 100644
--- a/src/Piece.h
+++ b/src/Piece.h
@@ -117,6 +117,11 @@ public:
bool isBlockUsed(int32_t index) const {
return bitfield->isUseBitSet(index);
}
+
+ /**
+ * Loses current bitfield state.
+ */
+ void reconfigure(int32_t length);
};
typedef SharedHandle<Piece> PieceHandle;
diff --git a/src/PieceStorage.h b/src/PieceStorage.h
index e41aeea6..64e6d523 100644
--- a/src/PieceStorage.h
+++ b/src/PieceStorage.h
@@ -36,9 +36,15 @@
#define _D_PIECE_STORAGE_H_
#include "common.h"
-#include "Peer.h"
-#include "Piece.h"
-#include "DiskAdaptor.h"
+#include "TimeA2.h"
+
+class Piece;
+extern typedef SharedHandle<Piece> PieceHandle;
+extern typedef deque<PieceHandle> Pieces;
+class Peer;
+extern typedef SharedHandle<Peer> PeerHandle;
+class DiskAdaptor;
+extern typedef SharedHandle<DiskAdaptor> DiskAdaptorHandle;
class PieceStorage {
public:
@@ -67,12 +73,30 @@ public:
virtual PieceHandle getMissingFastPiece(const PeerHandle& peer) = 0;
/**
+ * Returns a missing piece if available. Otherwise returns 0;
+ */
+ virtual PieceHandle getMissingPiece() = 0;
+
+ /**
+ * Returns a missing piece whose index is index.
+ * If a piece whose index is index is already acquired or currently used,
+ * then returns 0.
+ * Also returns 0 if any of missing piece is not available.
+ */
+ virtual PieceHandle getMissingPiece(int32_t index) = 0;
+
+ /**
* Returns the piece denoted by index.
* No status of the piece is changed in this method.
*/
virtual PieceHandle getPiece(int32_t index) = 0;
/**
+ * Marks the piece whose index is index as missing.
+ */
+ virtual void markPieceMissing(int32_t index) = 0;
+
+ /**
* Tells that the download of the specfied piece completes.
*/
virtual void completePiece(const PieceHandle& piece) = 0;
@@ -88,6 +112,8 @@ public:
*/
virtual bool hasPiece(int32_t index) = 0;
+ virtual bool isPieceUsed(int32_t index) = 0;
+
virtual int64_t getTotalLength() = 0;
virtual int64_t getFilteredTotalLength() = 0;
@@ -163,9 +189,15 @@ public:
virtual void markAllPiecesDone() = 0;
/**
- * Validates file integrity by comparing checksums.
+ * Sets all bits in bitfield(0 to length) to 1.
*/
- virtual void checkIntegrity() = 0;
+ virtual void markPiecesDone(int64_t length) = 0;
+
+ virtual void addInFlightPiece(const Pieces& pieces) = 0;
+
+ virtual int32_t countInFlightPiece() = 0;
+
+ virtual Pieces getInFlightPieces() = 0;
};
typedef SharedHandle<PieceStorage> PieceStorageHandle;
diff --git a/src/ConsoleFileAllocationMonitor.h b/src/PiecedSegment.cc
index f1c89eee..3588bfe1 100644
--- a/src/ConsoleFileAllocationMonitor.h
+++ b/src/PiecedSegment.cc
@@ -32,74 +32,69 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
-#ifndef _D_CONSOLE_FILE_ALLOCATION_MONITOR_H_
-#define _D_CONSOLE_FILE_ALLOCATION_MONITOR_H_
+#include "PiecedSegment.h"
+#include "Piece.h"
-#include "FileAllocationMonitor.h"
+PiecedSegment::PiecedSegment(int32_t pieceLength, const PieceHandle& piece):
+ _pieceLength(pieceLength), _overflowLength(0), _piece(piece)
+{
+ _writtenLength = _piece->getAllMissingBlockIndexes().front()*BLOCK_LENGTH;
+}
-class ConsoleFileAllocationMonitor : public FileAllocationMonitor {
-private:
- string filename;
- int64_t min;
- int64_t max;
- int64_t current;
-public:
- ConsoleFileAllocationMonitor():min(0), max(0), current(0) {}
+PiecedSegment::~PiecedSegment() {}
- virtual ~ConsoleFileAllocationMonitor() {}
+bool PiecedSegment::complete() const
+{
+ return _piece->pieceComplete();
+}
- virtual void setFilename(const string& filename) {
- this->filename = filename;
- }
+int32_t PiecedSegment::getIndex() const
+{
+ return _piece->getIndex();
+}
- virtual void setMinValue(const int64_t& min) {
- if(max < min) {
- this->min = max;
- } else {
- this->min = min;
- }
- }
-
- int64_t getMinValue() const {
- return min;
- }
+int64_t PiecedSegment::getPosition() const
+{
+ return ((int64_t)_piece->getIndex())*_pieceLength;
+}
- virtual void setMaxValue(const int64_t& max) {
- if(max < min) {
- this->max = min;
- } else {
- this->max = max;
- }
- }
+int64_t PiecedSegment::getPositionToWrite() const
+{
+ return getPosition()+_writtenLength;
+}
- int64_t getMaxValue() const {
- return max;
- }
+int32_t PiecedSegment::getLength() const
+{
+ return _piece->getLength();
+}
- virtual void setCurrentValue(const int64_t& current) {
- if(current > max) {
- this->current = max;
- } else {
- this->current = current;
- }
+void PiecedSegment::updateWrittenLength(int32_t bytes)
+{
+ int32_t newWrittenLength = _writtenLength+bytes;
+ if(newWrittenLength > _piece->getLength()) {
+ _overflowLength = newWrittenLength-_piece->getLength();
+ newWrittenLength = _piece->getLength();
}
-
- int64_t getCurrentValue() const {
- return current;
+ for(int32_t i = _writtenLength/BLOCK_LENGTH; i < newWrittenLength/BLOCK_LENGTH; ++i) {
+ _piece->completeBlock(i);
}
-
- virtual void showProgress();
-};
-
-class ConsoleFileAllocationMonitorFactory : public FileAllocationMonitorFactory {
-public:
- ConsoleFileAllocationMonitorFactory() {}
-
- virtual FileAllocationMonitorHandle createNewMonitor() {
- return new ConsoleFileAllocationMonitor();
+ if(newWrittenLength == _piece->getLength()) {
+ _piece->completeBlock(_piece->countBlock()-1);
}
-};
+ _writtenLength = newWrittenLength;
+}
+
+PieceHandle PiecedSegment::getPiece() const
+{
+ return _piece;
+}
-typedef SharedHandle<ConsoleFileAllocationMonitorFactory> ConsoleFileAllocationMonitorFactoryHandle;
+bool PiecedSegment::operator==(const PiecedSegment& segment) const
+{
+ return _piece == segment._piece;
+}
-#endif // _D_CONSOLE_FILE_ALLOCATION_MONITOR_H_
+bool PiecedSegment::operator!=(const PiecedSegment& segment) const
+{
+ return !(*this == segment);
+}
diff --git a/src/PiecedSegment.h b/src/PiecedSegment.h
new file mode 100644
index 00000000..4c778f05
--- /dev/null
+++ b/src/PiecedSegment.h
@@ -0,0 +1,94 @@
+/* <!-- 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_PIECED_SEGMENT_H_
+#define _D_PIECED_SEGMENT_H_
+
+#include "Segment.h"
+
+class PiecedSegment:public Segment {
+private:
+ /**
+ * Piece class has length property but it is a actual length of piece.
+ * The last piece likely have shorter length than the other length.
+ */
+ int32_t _pieceLength;
+ int32_t _writtenLength;
+ int32_t _overflowLength;
+ PieceHandle _piece;
+
+public:
+ PiecedSegment(int32_t pieceLength, const PieceHandle& piece);
+
+ virtual ~PiecedSegment();
+
+ virtual bool complete() const;
+
+ virtual int32_t getIndex() const;
+
+ virtual int64_t getPosition() const;
+
+ virtual int64_t getPositionToWrite() const;
+
+ virtual int32_t getLength() const;
+
+ virtual int32_t getSegmentLength() const
+ {
+ return _pieceLength;
+ }
+
+ virtual int32_t getWrittenLength() const
+ {
+ return _writtenLength;
+ }
+
+ virtual int32_t getOverflowLength() const
+ {
+ return _overflowLength;
+ }
+
+ virtual void updateWrittenLength(int32_t bytes);
+
+ virtual PieceHandle getPiece() const;
+
+ bool operator==(const PiecedSegment& segment) const;
+
+ bool operator!=(const PiecedSegment& segment) const;
+
+};
+
+typedef SharedHandle<PiecedSegment> PiecedSegmentHandle;
+
+#endif // _D_PIECED_SEGMENT_H_
+
diff --git a/src/PostDownloadHandler.cc b/src/PostDownloadHandler.cc
new file mode 100644
index 00000000..d7eab07e
--- /dev/null
+++ b/src/PostDownloadHandler.cc
@@ -0,0 +1,46 @@
+/* <!-- 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 "PostDownloadHandler.h"
+#include "Util.h"
+
+PostDownloadHandler::PostDownloadHandler(const string& extension, const Option* option):_extension(extension), _option(option)
+{}
+
+PostDownloadHandler::~PostDownloadHandler() {}
+
+bool PostDownloadHandler::canHandle(const string& path)
+{
+ return Util::endsWith(path, _extension);
+}
diff --git a/src/TorrentAutoSaveCommand.h b/src/PostDownloadHandler.h
index 86d31641..70a0b5ce 100644
--- a/src/TorrentAutoSaveCommand.h
+++ b/src/PostDownloadHandler.h
@@ -32,28 +32,32 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
-#ifndef _D_TORRENT_AUTO_SAVE_COMMAND_H_
-#define _D_TORRENT_AUTO_SAVE_COMMAND_H_
+#ifndef _D_POST_DOWNLOAD_HANDLER_H_
+#define _D_POST_DOWNLOAD_HANDLER_H_
-#include "BtContextAwareCommand.h"
-#include "TorrentDownloadEngine.h"
-#include "TimeA2.h"
-#include "BtContext.h"
+#include "common.h"
-class TorrentAutoSaveCommand : public BtContextAwareCommand {
+class Option;
+class RequestGroup;
+typedef SharedHandle<RequestGroup> RequestGroupHandle;
+typedef deque<RequestGroupHandle> RequestGroups;
+
+class PostDownloadHandler
+{
private:
- TorrentDownloadEngine* e;
- int32_t interval;
- Time checkPoint;
+ string _extension;
+protected:
+ const Option* _option;
public:
- TorrentAutoSaveCommand(int32_t cuid,
- TorrentDownloadEngine* e,
- const BtContextHandle& btContext,
- int32_t interval);
+ PostDownloadHandler(const string& extension, const Option* option);
+
+ virtual ~PostDownloadHandler();
- ~TorrentAutoSaveCommand();
+ bool canHandle(const string& path);
- bool execute();
+ virtual RequestGroups getNextRequestGroups(const string& path) = 0;
};
-#endif // _D_TORRENT_AUTO_SAVE_COMMAND_H_
+typedef SharedHandle<PostDownloadHandler> PostDownloadHandlerHandle;
+typedef deque<PostDownloadHandlerHandle> PostDownloadHandlers;
+#endif // _D_POST_DOWNLOAD_HANDLER_H_
diff --git a/src/ProgressAwareEntry.h b/src/ProgressAwareEntry.h
index 5b11845e..af306ae6 100644
--- a/src/ProgressAwareEntry.h
+++ b/src/ProgressAwareEntry.h
@@ -41,11 +41,11 @@ class ProgressAwareEntry {
public:
virtual ~ProgressAwareEntry() {}
- virtual int64_t getCurrentLength() const = 0;
+ virtual int64_t getCurrentLength() = 0;
- virtual int64_t getTotalLength() const = 0;
+ virtual int64_t getTotalLength() = 0;
- virtual bool finished() const = 0;
+ virtual bool finished() = 0;
};
typedef SharedHandle<ProgressAwareEntry> ProgressAwareEntryHandle;
diff --git a/src/RealtimeCommand.cc b/src/RealtimeCommand.cc
index a613fc59..4c9eff58 100644
--- a/src/RealtimeCommand.cc
+++ b/src/RealtimeCommand.cc
@@ -41,7 +41,7 @@ bool RealtimeCommand::execute()
try {
return executeInternal();
} catch(Exception* e) {
- _requestGroup->getSegmentMan()->errors++;
+ //_requestGroup->getSegmentMan()->errors++;
bool r = handleException(e);
delete e;
return r;
diff --git a/src/RealtimeCommand.h b/src/RealtimeCommand.h
index 915aa56b..203c0eeb 100644
--- a/src/RealtimeCommand.h
+++ b/src/RealtimeCommand.h
@@ -39,16 +39,17 @@
#include "RequestGroup.h"
#include "DownloadEngine.h"
#include "Exception.h"
+#include "RequestGroupAware.h"
-class RealtimeCommand : public Command {
+class RealtimeCommand : public Command, public RequestGroupAware {
protected:
- RequestGroup* _requestGroup;
DownloadEngine* _e;
public:
RealtimeCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e):
Command(cuid),
- _requestGroup(requestGroup),
- _e(e) {}
+ RequestGroupAware(requestGroup),
+ _e(e)
+ {}
virtual ~RealtimeCommand() {}
diff --git a/src/Request.cc b/src/Request.cc
index 938c6186..bf8893f3 100644
--- a/src/Request.cc
+++ b/src/Request.cc
@@ -41,7 +41,7 @@ const string Request::METHOD_GET = "get";
const string Request::METHOD_HEAD = "head";
-Request::Request():port(0), tryCount(0), keepAlive(true), method(METHOD_GET),
+Request::Request():port(0), tryCount(0), keepAlive(false), method(METHOD_GET),
_httpAuthResolver(0),
_httpProxyAuthResolver(0),
_ftpAuthResolver(0),
diff --git a/src/RequestGroup.cc b/src/RequestGroup.cc
index 01e95a40..6d75bad0 100644
--- a/src/RequestGroup.cc
+++ b/src/RequestGroup.cc
@@ -34,228 +34,244 @@
/* copyright --> */
#include "RequestGroup.h"
#include "DownloadEngine.h"
+#include "DefaultSegmentManFactory.h"
+#include "NullProgressInfoFile.h"
+#include "SegmentManFactory.h"
+#include "Dependency.h"
#include "prefs.h"
-#include "DefaultDiskWriter.h"
#include "RequestFactory.h"
#include "InitiateConnectionCommandFactory.h"
#include "CUIDCounter.h"
-#include "DlAbortEx.h"
#include "File.h"
#include "message.h"
-#include "DlAbortEx.h"
#include "Util.h"
-#include "FatalException.h"
-#include "DownloadCommand.h"
+#include "BtRegistry.h"
+#include "LogFactory.h"
+#include "DiskAdaptor.h"
+#include "DiskWriterFactory.h"
#ifdef ENABLE_MESSAGE_DIGEST
-#include "CheckIntegrityCommand.h"
-#include "CheckIntegrityEntry.h"
+# include "CheckIntegrityCommand.h"
#endif // ENABLE_MESSAGE_DIGEST
+#ifdef ENABLE_BITTORRENT
+# include "BtCheckIntegrityEntry.h"
+# include "DefaultPieceStorage.h"
+# include "DefaultBtProgressInfoFile.h"
+# include "DefaultPeerStorage.h"
+# include "DefaultBtAnnounce.h"
+# include "BtSetup.h"
+# include "BtFileAllocationEntry.h"
+# include "BtPostDownloadHandler.h"
+#endif // ENABLE_BITTORRENT
+#ifdef ENABLE_METALINK
+# include "MetalinkPostDownloadHandler.h"
+#endif // ENABLE_METALINK
#include <cerrno>
-SegmentManHandle RequestGroup::initSegmentMan()
+int32_t RequestGroup::_gidCounter = 0;
+
+RequestGroup::RequestGroup(const Option* option,
+ const Strings& uris):
+ _gid(++_gidCounter),
+ _hintTotalLength(0),
+ _uris(uris),
+ _numConcurrentCommand(0),
+ _numStreamConnection(0),
+ _numCommand(0),
+ _segmentMan(0),
+ _segmentManFactory(new DefaultSegmentManFactory(option)),
+ _downloadContext(0),
+ _pieceStorage(0),
+ _progressInfoFile(new NullProgressInfoFile()),
+ _diskWriterFactory(0),
+ _dependency(0),
+ _preLocalFileCheckEnabled(true),
+ _haltRequested(false),
+ _option(option),
+ _logger(LogFactory::getInstance())
{
- _segmentMan = _segmentManFactory->createNewInstance();
- _segmentMan->ufilename = _ufilename;
- if(!_topDir.empty() && _topDir != ".") {
- _segmentMan->dir += "/"+_topDir;
+ if(_option->get(PREF_FILE_ALLOCATION) == V_PREALLOC) {
+ _fileAllocationEnabled = true;
+ } else {
+ _fileAllocationEnabled = false;
}
- return _segmentMan;
+ initializePostDownloadHandler();
}
-Commands RequestGroup::createNextCommandWithAdj(DownloadEngine* e, int32_t numAdj)
+RequestGroup::~RequestGroup() {}
+
+SegmentManHandle RequestGroup::initSegmentMan()
{
- int32_t numCommand = _numConcurrentCommand == 0 ? _uris.size() : _numConcurrentCommand+numAdj;
- return createNextCommand(e, numCommand, "GET");
+ _segmentMan = _segmentManFactory->createNewInstance(_downloadContext,
+ _pieceStorage);
+ return _segmentMan;
}
-Commands RequestGroup::createNextCommand(DownloadEngine* e, int32_t numCommand, const string& method)
+bool RequestGroup::downloadFinished() const
{
- Commands commands;
- for(;!_uris.empty() && commands.size() < (size_t)numCommand; _uris.pop_front()) {
- string uri = _uris.front();
- _spentUris.push_back(uri);
- RequestHandle req = RequestFactorySingletonHolder::instance()->createRequest();
- req->setReferer(_option->get(PREF_REFERER));
- req->setMethod(method);
- if(req->setUrl(uri)) {
- commands.push_back(InitiateConnectionCommandFactory::createInitiateConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(), req, this, e));
- } else {
- logger->error(MSG_UNRECOGNIZED_URI,
- req->getUrl().c_str());
- }
+ if(_pieceStorage.isNull()) {
+ return false;
+ } else {
+ return _pieceStorage->downloadFinished();
}
- return commands;
}
-void RequestGroup::initBitfield()
+void RequestGroup::closeFile()
{
- _segmentMan->initBitfield(_option->getAsInt(PREF_SEGMENT_SIZE),
- _segmentMan->totalSize);
+ if(!_pieceStorage.isNull()) {
+ _pieceStorage->getDiskAdaptor()->closeFile();
+ }
}
-void RequestGroup::openExistingFile()
+Commands RequestGroup::createInitialCommand(DownloadEngine* e)
{
- _segmentMan->diskWriter->openExistingFile(_segmentMan->getFilePath());
-}
+ // If this includes torrent download, then this method returns
+ // the command that torrent download requires, such as
+ // TrackerWatcherCommand and so on.
-void RequestGroup::markAllPiecesDone()
-{
- _segmentMan->markAllPiecesDone();
-}
+ // It is better to avoid to using BtTorrent specific classes here.
+#ifdef ENABLE_BITTORRENT
+ {
+ BtContextHandle btContext = _downloadContext;
+ if(!btContext.isNull()) {
+ if(btContext->getFileEntries().size() > 1) {
+ // this is really multi file torrent.
+ // clear http/ftp uris because the current implementation does not
+ // allow integrating multi-file torrent and http/ftp.
+ _logger->debug("Clearing http/ftp URIs because the current implementation does not allow integrating multi-file torrent and http/ftp.");
+ _uris.clear();
+ }
-void RequestGroup::markExistingPiecesDone()
-{
- _segmentMan->markPieceDone(File(_segmentMan->getFilePath()).size());
-}
+ _pieceStorage = new DefaultPieceStorage(btContext, _option);
+ _pieceStorage->initStorage();
+ initSegmentMan();
-void RequestGroup::markPieceDone(int64_t length)
-{
- _segmentMan->markPieceDone(length);
-}
+ BtProgressInfoFileHandle progressInfoFile =
+ new DefaultBtProgressInfoFile(_downloadContext,
+ _pieceStorage,
+ _option);
+
+ BtRegistry::registerBtContext(btContext->getInfoHashAsString(), btContext);
+ BtRegistry::registerPieceStorage(btContext->getInfoHashAsString(),
+ _pieceStorage);
+ BtRegistry::registerBtProgressInfoFile(btContext->getInfoHashAsString(),
+ progressInfoFile);
-void RequestGroup::shouldCancelDownloadForSafety()
-{
- if(fileExists() && !segmentFileExists()) {
- if(_option->get(PREF_AUTO_FILE_RENAMING) == V_TRUE) {
- if(tryAutoFileRenaming()) {
- logger->notice("File already exists. Renamed to %s.",
- getFilePath().c_str());
+
+ BtRuntimeHandle btRuntime = new BtRuntime();
+ btRuntime->setListenPort(_option->getAsInt(PREF_LISTEN_PORT));
+ BtRegistry::registerBtRuntime(btContext->getInfoHashAsString(), btRuntime);
+
+ PeerStorageHandle peerStorage = new DefaultPeerStorage(btContext, _option);
+ BtRegistry::registerPeerStorage(btContext->getInfoHashAsString(), peerStorage);
+
+ BtAnnounceHandle btAnnounce = new DefaultBtAnnounce(btContext, _option);
+ BtRegistry::registerBtAnnounce(btContext->getInfoHashAsString(), btAnnounce);
+ btAnnounce->shuffleAnnounce();
+
+ BtRegistry::registerPeerObjectCluster(btContext->getInfoHashAsString(),
+ new PeerObjectCluster());
+
+ // Call Load, Save and file allocation command here
+ if(progressInfoFile->exists()) {
+ // load .aria2 file if it exists.
+ progressInfoFile->load();
+ _pieceStorage->getDiskAdaptor()->openFile();
} else {
- logger->notice("File renaming failed: %s",
- _segmentMan->getFilePath().c_str());
- throw new FatalException(EX_DOWNLOAD_ABORTED);
+ if(_pieceStorage->getDiskAdaptor()->fileExists()) {
+ if(_option->get(PREF_ALLOW_OVERWRITE) != V_TRUE) {
+ _logger->error(MSG_FILE_ALREADY_EXISTS,
+ getFilePath().c_str(),
+ progressInfoFile->getFilename().c_str());
+ // TODO we need this->haltRequested = true?
+ return Commands();
+ } else {
+ _pieceStorage->getDiskAdaptor()->openFile();
+ }
+ } else {
+ _pieceStorage->getDiskAdaptor()->openFile();
+ }
}
- } else if(_option->get(PREF_ALLOW_OVERWRITE) != V_TRUE) {
- logger->notice(MSG_FILE_ALREADY_EXISTS,
- _segmentMan->getFilePath().c_str(),
- _segmentMan->getSegmentFilePath().c_str());
- throw new FatalException(EX_DOWNLOAD_ABORTED);
+ _progressInfoFile = progressInfoFile;
+ Commands commands;
+ CheckIntegrityEntryHandle entry = new BtCheckIntegrityEntry(this);
+#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
+#endif // ENABLE_MESSAGE_DIGEST
+ {
+ commands = entry->prepareForNextAction(e);
+ }
+ return commands;
}
}
+#endif // ENABLE_BITTORRENT
+ return createNextCommand(e, 1);
}
-void RequestGroup::initAndOpenFile()
-{
- File d(getDir());
- if(d.isDir()) {
- } else if(d.exists()) {
- throw new FatalException(EX_MAKE_DIR, getDir().c_str(), MSG_NOT_DIRECTORY);
- } else if(!d.mkdirs()) {
- throw new FatalException(EX_MAKE_DIR, getDir().c_str(), strerror(errno));
- }
- _segmentMan->diskWriter->initAndOpenFile(_segmentMan->getFilePath());
-}
-
-bool RequestGroup::needsFileAllocation() const
-{
- return _option->get(PREF_FILE_ALLOCATION) == V_PREALLOC
- && File(_segmentMan->getFilePath()).size() < _segmentMan->totalSize;
-}
-
-bool RequestGroup::fileExists() const
-{
- return _segmentMan->fileExists();
-}
-
-bool RequestGroup::segmentFileExists() const
+Commands RequestGroup::createNextCommandWithAdj(DownloadEngine* e, int32_t numAdj)
{
- return _segmentMan->segmentFileExists();
+ int32_t numCommand = _numConcurrentCommand == 0 ? _uris.size() : _numConcurrentCommand+numAdj;
+ return createNextCommand(e, numCommand, "GET");
}
-string RequestGroup::getFilePath() const
+Commands RequestGroup::createNextCommand(DownloadEngine* e, int32_t numCommand, const string& method)
{
- if(_segmentMan.isNull()) {
- return "";
- } else {
- return _segmentMan->getFilePath();
+ Commands commands;
+ for(;!_uris.empty() && numCommand--; _uris.pop_front()) {
+ string uri = _uris.front();
+ _spentUris.push_back(uri);
+ RequestHandle req = RequestFactorySingletonHolder::instance()->createRequest();
+ req->setReferer(_option->get(PREF_REFERER));
+ req->setMethod(method);
+ if(req->setUrl(uri)) {
+ commands.push_back(InitiateConnectionCommandFactory::createInitiateConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(), req, this, e));
+ } else {
+ _logger->error(MSG_UNRECOGNIZED_URI, req->getUrl().c_str());
+ }
}
+ return commands;
}
-string RequestGroup::getDir() const
+string RequestGroup::getFilePath() const
{
- if(_segmentMan.isNull()) {
+ assert(!_downloadContext.isNull());
+ if(_downloadContext.isNull()) {
return "";
} else {
- return _segmentMan->dir;
+ return _downloadContext->getActualBasePath();
}
}
-void RequestGroup::loadAndOpenFile()
+int64_t RequestGroup::getTotalLength() const
{
- bool segFileExists = segmentFileExists();
- if(segFileExists) {
- load();
- openExistingFile();
- } else if(fileExists() && _option->get(PREF_CONTINUE) == V_TRUE) {
- File existingFile(getFilePath());
- if(getTotalLength() < existingFile.size()) {
- throw new DlAbortEx(EX_FILE_LENGTH_MISMATCH_BETWEEN_LOCAL_AND_REMOTE,
- getFilePath().c_str(),
- Util::llitos(existingFile.size()).c_str(),
- Util::llitos(getTotalLength()).c_str());
- }
- initBitfield();
- openExistingFile();
- _segmentMan->markPieceDone(existingFile.size());
+ if(_pieceStorage.isNull()) {
+ return 0;
} else {
- shouldCancelDownloadForSafety();
- initBitfield();
-#ifdef ENABLE_MESSAGE_DIGEST
- if(fileExists() && _option->get(PREF_CHECK_INTEGRITY) == V_TRUE) {
- openExistingFile();
+ if(_pieceStorage->isSelectiveDownloadingMode()) {
+ return _pieceStorage->getFilteredTotalLength();
} else {
- initAndOpenFile();
+ return _pieceStorage->getTotalLength();
}
-#else // ENABLE_MESSAGE_DIGEST
- initAndOpenFile();
-#endif // ENABLE_MESSAGE_DIGEST
}
}
-bool RequestGroup::downloadFinishedByFileLength()
+int64_t RequestGroup::getCompletedLength() const
{
- if(_segmentMan->segmentFileExists()) {
- return false;
- }
- File existingFile(getFilePath());
- if(existingFile.exists() &&
- getTotalLength() == existingFile.size()) {
- _segmentMan->downloadStarted = true;
- initBitfield();
- _segmentMan->markAllPiecesDone();
- return true;
+ if(_pieceStorage.isNull()) {
+ return 0;
} else {
- return false;
- }
-}
-
-void RequestGroup::prepareForNextAction(int cuid, const RequestHandle& req, DownloadEngine* e, DownloadCommand* downloadCommand)
-{
- File existingFile(getFilePath());
-#ifdef ENABLE_MESSAGE_DIGEST
- if(existingFile.size() > 0 && _option->get(PREF_CHECK_INTEGRITY) == V_TRUE) {
- // purge SegmentEntries
- _segmentMan->purgeSegmentEntry();
-
- CheckIntegrityEntryHandle entry = new CheckIntegrityEntry(cuid, req, this, downloadCommand);
- entry->initValidator();
- CheckIntegrityCommand* command = new CheckIntegrityCommand(cuid, this, e, entry);
- e->commands.push_back(command);
- } else
-#endif // ENABLE_MESSAGE_DIGEST
- if(needsFileAllocation()) {
- FileAllocationEntryHandle entry = new FileAllocationEntry(cuid, req, this, downloadCommand, existingFile.size());
- e->_fileAllocationMan->pushFileAllocationEntry(entry);
+ if(_pieceStorage->isSelectiveDownloadingMode()) {
+ return _pieceStorage->getFilteredCompletedLength();
} else {
- if(downloadCommand) {
- e->commands.push_back(downloadCommand);
- } else {
- Commands commands = createNextCommandWithAdj(e, -1);
- Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, req, this, e);
- commands.push_front(command);
- e->addCommand(commands);
- }
+ return _pieceStorage->getCompletedLength();
}
+ }
}
void RequestGroup::validateFilename(const string& expectedFilename,
@@ -286,12 +302,12 @@ void RequestGroup::validateTotalLength(int64_t expectedTotalLength,
void RequestGroup::validateFilename(const string& actualFilename) const
{
- validateFilename(_segmentMan->filename, actualFilename);
+ validateFilename(_downloadContext->getFileEntries().front()->getBasename(), actualFilename);
}
void RequestGroup::validateTotalLength(int64_t actualTotalLength) const
{
- validateTotalLength(_segmentMan->totalSize, actualTotalLength);
+ validateTotalLength(getTotalLength(), actualTotalLength);
}
void RequestGroup::validateFilenameByHint(const string& actualFilename) const
@@ -304,31 +320,186 @@ void RequestGroup::validateTotalLengthByHint(int64_t actualTotalLength) const
validateTotalLength(_hintTotalLength, actualTotalLength);
}
-void RequestGroup::setUserDefinedFilename(const string& filename)
+void RequestGroup::increaseStreamConnection()
{
- _ufilename = filename;
+ ++_numStreamConnection;
}
-int64_t RequestGroup::getExistingFileLength() const
+void RequestGroup::decreaseStreamConnection()
{
- return File(getFilePath()).size();
+ --_numStreamConnection;
}
-bool RequestGroup::tryAutoFileRenaming()
+int32_t RequestGroup::getNumConnection() const
{
- string filepath = getFilePath();
- if(filepath.empty()) {
- return false;
+ int32_t numConnection = _numStreamConnection;
+#ifdef ENABLE_BITTORRENT
+ {
+ BtContextHandle btContext = _downloadContext;
+ if(!btContext.isNull()) {
+ BtRuntimeHandle btRuntime = BT_RUNTIME(btContext);
+ if(!btRuntime.isNull()) {
+ numConnection += btRuntime->getConnections();
+ }
+ }
}
- for(int32_t i = 1; i < 10000; ++i) {
- File newfile(filepath+"."+Util::itos(i));
- if(!newfile.exists()) {
- _ufilename = newfile.getBasename();
- if(!_segmentMan.isNull()) {
- _segmentMan->ufilename = _ufilename;
+#endif // ENABLE_BITTORRENT
+ return numConnection;
+}
+
+void RequestGroup::increaseNumCommand()
+{
+ ++_numCommand;
+}
+
+void RequestGroup::decreaseNumCommand()
+{
+ --_numCommand;
+}
+
+
+TransferStat RequestGroup::calculateStat()
+{
+ TransferStat stat;
+#ifdef ENABLE_BITTORRENT
+ {
+ BtContextHandle btContext = _downloadContext;
+ if(!btContext.isNull()) {
+ PeerStorageHandle peerStorage = PEER_STORAGE(btContext);
+ if(!peerStorage.isNull()) {
+ stat = peerStorage->calculateStat();
+ }
+ }
+ }
+#endif // ENABLE_BITTORRENT
+ if(!_segmentMan.isNull()) {
+ stat.setDownloadSpeed(stat.getDownloadSpeed()+_segmentMan->calculateDownloadSpeed());
+ }
+ return stat;
+}
+
+void RequestGroup::setHaltRequested(bool f)
+{
+ _haltRequested = f;
+#ifdef ENABLE_BITTORRENT
+ {
+ BtContextHandle btContext = _downloadContext;
+ if(!btContext.isNull()) {
+ BtRuntimeHandle btRuntime = BT_RUNTIME(btContext);
+ if(!btRuntime.isNull()) {
+ btRuntime->setHalt(f);
}
- return true;
}
}
- return false;
+#endif // ENABLE_BITTORRENT
+}
+
+void RequestGroup::releaseRuntimeResource()
+{
+#ifdef ENABLE_BITTORRENT
+ BtContextHandle btContext = _downloadContext;
+ if(!btContext.isNull()) {
+ BtRegistry::unregister(btContext->getInfoHashAsString());
+ }
+#endif // ENABLE_BITTORRENT
+ if(!_pieceStorage.isNull()) {
+ _pieceStorage->removeAdvertisedPiece(0);
+ }
+}
+
+RequestGroups RequestGroup::postDownloadProcessing()
+{
+ for(PostDownloadHandlers::const_iterator itr = _postDownloadHandlers.begin();
+ itr != _postDownloadHandlers.end(); ++itr) {
+ if((*itr)->canHandle(getFilePath())) {
+ return (*itr)->getNextRequestGroups(getFilePath());
+ }
+ }
+ return RequestGroups();
+}
+
+void RequestGroup::initializePostDownloadHandler()
+{
+ _postDownloadHandlers.push_back(new BtPostDownloadHandler(_option));
+ _postDownloadHandlers.push_back(new MetalinkPostDownloadHandler(_option));
+}
+
+Strings RequestGroup::getUris() const
+{
+ Strings temp(_spentUris.begin(), _spentUris.end());
+ temp.insert(temp.end(), _uris.begin(), _uris.end());
+ return temp;
+}
+
+bool RequestGroup::isDependencyResolved()
+{
+ if(_dependency.isNull()) {
+ return true;
+ }
+ return _dependency->resolve();
+}
+
+void RequestGroup::setSegmentManFactory(const SegmentManFactoryHandle& segmentManFactory)
+{
+ _segmentManFactory = segmentManFactory;
+}
+
+void RequestGroup::dependsOn(const DependencyHandle& dep)
+{
+ _dependency = dep;
+}
+
+void RequestGroup::setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory)
+{
+ _diskWriterFactory = diskWriterFactory;
+}
+
+DiskWriterFactoryHandle RequestGroup::getDiskWriterFactory() const
+{
+ return _diskWriterFactory;
+}
+
+void RequestGroup::addPostDownloadHandler(const PostDownloadHandlerHandle& handler)
+{
+ _postDownloadHandlers.push_back(handler);
+}
+
+void RequestGroup::clearPostDowloadHandler()
+{
+ _postDownloadHandlers.clear();
+}
+
+SegmentManHandle RequestGroup::getSegmentMan() const
+{
+ return _segmentMan;
+}
+
+DownloadContextHandle RequestGroup::getDownloadContext() const
+{
+ return _downloadContext;
+}
+
+void RequestGroup::setDownloadContext(const DownloadContextHandle& downloadContext)
+{
+ _downloadContext = downloadContext;
+}
+
+PieceStorageHandle RequestGroup::getPieceStorage() const
+{
+ return _pieceStorage;
+}
+
+void RequestGroup::setPieceStorage(const PieceStorageHandle& pieceStorage)
+{
+ _pieceStorage = pieceStorage;
+}
+
+BtProgressInfoFileHandle RequestGroup::getProgressInfoFile() const
+{
+ return _progressInfoFile;
+}
+
+void RequestGroup::setProgressInfoFile(const BtProgressInfoFileHandle& progressInfoFile)
+{
+ _progressInfoFile = progressInfoFile;
}
diff --git a/src/RequestGroup.h b/src/RequestGroup.h
index 83317786..f60aea33 100644
--- a/src/RequestGroup.h
+++ b/src/RequestGroup.h
@@ -36,38 +36,86 @@
#define _D_REQUEST_GROUP_H_
#include "common.h"
-#include "SegmentMan.h"
-#include "LogFactory.h"
-#include "Command.h"
-#include "SegmentManFactory.h"
-#include "DefaultSegmentManFactory.h"
-#ifdef ENABLE_MESSAGE_DIGEST
-# include "ChunkChecksum.h"
-# include "Checksum.h"
-#endif // ENABLE_MESSAGE_DIGEST
-
-class DownloadCommand;
+#include "TransferStat.h"
class DownloadEngine;
+class SegmentMan;
+extern typedef SharedHandle<SegmentMan> SegmentManHandle;
+class SegmentManFactory;
+extern typedef SharedHandle<SegmentManFactory> SegmentManFactoryHandle;
+class Command;
+extern typedef deque<Command*> Commands;
+class DownloadContext;
+extern typedef SharedHandle<DownloadContext> DownloadContextHandle;
+class PieceStorage;
+extern typedef SharedHandle<PieceStorage> PieceStorageHandle;
+class BtProgressInfoFile;
+extern typedef SharedHandle<BtProgressInfoFile> BtProgressInfoFileHandle;
+class Dependency;
+extern typedef SharedHandle<Dependency> DependencyHandle;
+class DlAbortEx;
+class PostDownloadHandler;
+extern typedef SharedHandle<PostDownloadHandler> PostDownloadHandlerHandle;
+extern typedef deque<PostDownloadHandlerHandle> PostDownloadHandlers;
+class DiskWriterFactory;
+extern typedef SharedHandle<DiskWriterFactory> DiskWriterFactoryHandle;
+class Option;
+class Logger;
+
+class RequestGroup;
+extern typedef SharedHandle<RequestGroup> RequestGroupHandle;
+extern typedef deque<RequestGroupHandle> RequestGroups;
class RequestGroup {
private:
+ static int32_t _gidCounter;
+
int32_t _gid;
+
+ /**
+ * Hint for total length and filename.
+ * These values are used to verify whether the file http/ftp server sends back
+ * is correct one.
+ */
int64_t _hintTotalLength;
string _hintFilename;
- string _ufilename;
- string _topDir;
+
Strings _uris;
Strings _spentUris;
+
+ int32_t _numConcurrentCommand;
+
+ /**
+ * This is the number of connections used in streaming protocol(http/ftp)
+ */
+ int32_t _numStreamConnection;
+
+ int32_t _numCommand;
+
SegmentManHandle _segmentMan;
SegmentManFactoryHandle _segmentManFactory;
+
+ DownloadContextHandle _downloadContext;
+
+ PieceStorageHandle _pieceStorage;
+
+ BtProgressInfoFileHandle _progressInfoFile;
+
+ DiskWriterFactoryHandle _diskWriterFactory;
+
+ DependencyHandle _dependency;
+
+ bool _fileAllocationEnabled;
+
+ bool _preLocalFileCheckEnabled;
+
+ bool _haltRequested;
+
+ PostDownloadHandlers _postDownloadHandlers;
+
const Option* _option;
- const Logger* logger;
-#ifdef ENABLE_MESSAGE_DIGEST
- ChunkChecksumHandle _chunkChecksum;
- ChecksumHandle _checksum;
-#endif // ENABLE_MESSAGE_DIGEST
- int32_t _numConcurrentCommand;
+
+ const Logger* _logger;
void validateFilename(const string& expectedFilename,
const string& actualFilename) const;
@@ -75,56 +123,20 @@ private:
void validateTotalLength(int64_t expectedTotalLength,
int64_t actualTotalLength) const;
+ void initializePostDownloadHandler();
public:
+ RequestGroup(const Option* option, const Strings& uris);
- int32_t numConnection;
-
- bool isTorrent;
-
- RequestGroup(const Strings& uris, const Option* option):
- _gid(0),
- _hintTotalLength(0),
- _uris(uris),
- _segmentMan(0),
- _segmentManFactory(new DefaultSegmentManFactory(option)),
- _option(option),
- logger(LogFactory::getInstance()),
-#ifdef ENABLE_MESSAGE_DIGEST
- _chunkChecksum(0),
- _checksum(0),
-#endif // ENABLE_MESSAGE_DIGEST
- _numConcurrentCommand(0),
- numConnection(0),
- isTorrent(false) {}
-
- RequestGroup(const string& uri, const Option* option):
- _gid(0),
- _hintTotalLength(0),
- _segmentMan(0),
- _segmentManFactory(new DefaultSegmentManFactory(option)),
- _option(option),
- logger(LogFactory::getInstance()),
-#ifdef ENABLE_MESSAGE_DIGEST
- _chunkChecksum(0),
- _checksum(0),
-#endif // ENABLE_MESSAGE_DIGEST
- _numConcurrentCommand(0),
- numConnection(0),
- isTorrent(false)
- {
- _uris.push_back(uri);
- }
-
+ ~RequestGroup();
/**
* Reinitializes SegmentMan based on current property values and
* returns new one.
*/
SegmentManHandle initSegmentMan();
- SegmentManHandle getSegmentMan() const
- {
- return _segmentMan;
- }
+ SegmentManHandle getSegmentMan() const;
+
+ Commands createInitialCommand(DownloadEngine* e);
Commands createNextCommandWithAdj(DownloadEngine* e, int32_t numAdj);
@@ -135,98 +147,17 @@ public:
_uris.push_back(uri);
}
-#ifdef ENABLE_MESSAGE_DIGEST
- void setChunkChecksum(const ChunkChecksumHandle& chunkChecksum)
- {
- _chunkChecksum = chunkChecksum;
- }
-
- ChunkChecksumHandle getChunkChecksum() const
- {
- return _chunkChecksum;
- }
-
- void setChecksum(const ChecksumHandle& checksum)
- {
- _checksum = checksum;
- }
-
- ChecksumHandle getChecksum() const
- {
- return _checksum;
- }
-#endif // ENABLE_MESSAGE_DIGEST
-
- void initBitfield();
-
- void openExistingFile();
-
- void markAllPiecesDone();
-
- void markExistingPiecesDone();
-
- void markPieceDone(int64_t length);
-
- void shouldCancelDownloadForSafety();
-
- void initAndOpenFile();
-
- bool needsFileAllocation() const;
-
- bool downloadFinished() const
- {
- if(_segmentMan.isNull()) {
- return false;
- } else {
- return _segmentMan->finished();
- }
- }
-
- void load()
- {
- _segmentMan->load();
- }
-
- void save()
- {
- _segmentMan->save();
- }
-
- void remove()
- {
- _segmentMan->remove();
- }
-
- void closeFile()
- {
- _segmentMan->diskWriter->closeFile();
- }
+ bool downloadFinished() const;
- bool fileExists() const;
-
- bool segmentFileExists() const;
+ void closeFile();
string getFilePath() const;
string getDir() const;
- int64_t getExistingFileLength() const;
-
- int64_t getTotalLength() const
- {
- return _segmentMan->totalSize;
- }
-
- int64_t getDownloadLength() const
- {
- return _segmentMan->getDownloadLength();
- }
-
- void loadAndOpenFile();
-
- void prepareForNextAction(int cuid, const RequestHandle& req, DownloadEngine* e, DownloadCommand* downloadCommand = 0);
+ int64_t getTotalLength() const;
- bool downloadFinishedByFileLength();
+ int64_t getCompletedLength() const;
const string& getHintFilename() const
{
@@ -258,12 +189,7 @@ public:
return _spentUris;
}
- Strings getUris() const
- {
- Strings temp(_spentUris.begin(), _spentUris.end());
- temp.insert(temp.end(), _uris.begin(), _uris.end());
- return temp;
- }
+ Strings getUris() const;
/**
* Compares expected filename with specified actualFilename.
@@ -281,42 +207,99 @@ public:
void validateTotalLengthByHint(int64_t actualTotalLength) const;
- void setSegmentManFactory(const SegmentManFactoryHandle& segmentManFactory)
- {
- _segmentManFactory = segmentManFactory;
- }
+ void setSegmentManFactory(const SegmentManFactoryHandle& segmentManFactory);
void setNumConcurrentCommand(int32_t num)
{
_numConcurrentCommand = num;
}
- void setUserDefinedFilename(const string& filename);
+ int32_t getGID() const
+ {
+ return _gid;
+ }
+
+ TransferStat calculateStat();
+
+ DownloadContextHandle getDownloadContext() const;
+
+ void setDownloadContext(const DownloadContextHandle& downloadContext);
+
+ PieceStorageHandle getPieceStorage() const;
+
+ void setPieceStorage(const PieceStorageHandle& pieceStorage);
+
+ BtProgressInfoFileHandle getProgressInfoFile() const;
+
+ void setProgressInfoFile(const BtProgressInfoFileHandle& progressInfoFile);
+
+ void increaseStreamConnection();
+
+ void decreaseStreamConnection();
+
+ int32_t getNumConnection() const;
+
+ void increaseNumCommand();
+
+ void decreaseNumCommand();
+
+ int32_t getNumCommand() const
+ {
+ return _numCommand;
+ }
+
+ // TODO is it better to move the following 2 methods to SingleFileDownloadContext?
+ void setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory);
- void setGID(int32_t gid)
+ DiskWriterFactoryHandle getDiskWriterFactory() const;
+
+ void setFileAllocationEnabled(bool f)
{
- _gid = gid;
+ _fileAllocationEnabled = f;
}
- int32_t getGID() const
+ bool isFileAllocationEnabled() const
{
- return _gid;
+ return _fileAllocationEnabled;
+ }
+
+ /**
+ * Setting _preLocalFileCheckEnabled to false, then skip the check to see
+ * if a file is already exists and control file exists etc.
+ * Always open file with DiskAdaptor::initAndOpenFile()
+ */
+ void setPreLocalFileCheckEnabled(bool f)
+ {
+ _preLocalFileCheckEnabled = f;
}
- void setTopDir(const string& topDir)
+ bool isPreLocalFileCheckEnabled() const
{
- _topDir = topDir;
+ return _preLocalFileCheckEnabled;
}
- int32_t calculateDownloadSpeed() const
+ void setHaltRequested(bool f);
+
+ bool isHaltRequested() const
{
- return _segmentMan->calculateDownloadSpeed();
+ return _haltRequested;
}
- bool tryAutoFileRenaming();
+ void dependsOn(const DependencyHandle& dep);
+
+ bool isDependencyResolved();
+
+ void releaseRuntimeResource();
+
+ RequestGroups postDownloadProcessing();
+
+ void addPostDownloadHandler(const PostDownloadHandlerHandle& handler);
+
+ void clearPostDowloadHandler();
};
typedef SharedHandle<RequestGroup> RequestGroupHandle;
+typedef WeakHandle<RequestGroup> RequestGroupWeakHandle;
typedef deque<RequestGroupHandle> RequestGroups;
#endif // _D_REQUEST_GROUP_H_
diff --git a/src/TrackerSegmentManFactory.cc b/src/RequestGroupAware.cc
index e203c2bd..c76f9ba8 100644
--- a/src/TrackerSegmentManFactory.cc
+++ b/src/RequestGroupAware.cc
@@ -32,13 +32,16 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
-#include "TrackerSegmentManFactory.h"
-#include "ByteArrayDiskWriter.h"
+#include "RequestGroupAware.h"
+#include "RequestGroup.h"
-SegmentManHandle TrackerSegmentManFactory::createNewInstance()
+RequestGroupAware::RequestGroupAware(RequestGroup* requestGroup):
+ _requestGroup(requestGroup)
{
- SegmentManHandle segmentMan = new SegmentMan();
- segmentMan->diskWriter = new ByteArrayDiskWriter();
- segmentMan->option = _option;
- return segmentMan;
+ _requestGroup->increaseNumCommand();
+}
+
+RequestGroupAware::~RequestGroupAware()
+{
+ _requestGroup->decreaseNumCommand();
}
diff --git a/src/TorrentConsoleDownloadEngine.h b/src/RequestGroupAware.h
index dea43c82..1f5e6283 100644
--- a/src/TorrentConsoleDownloadEngine.h
+++ b/src/RequestGroupAware.h
@@ -32,19 +32,20 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
-#ifndef _D_TORRENT_CONSOLE_DOWNLOAD_ENGINE_H_
-#define _D_TORRENT_CONSOLE_DOWNLOAD_ENGINE_H_
+#ifndef _D_REQUEST_GROUP_AWARE_H_
+#define _D_REQUEST_GROUP_AWARE_H_
-#include "TorrentDownloadEngine.h"
+#include "common.h"
-class TorrentConsoleDownloadEngine : public TorrentDownloadEngine {
+class RequestGroup;
+
+class RequestGroupAware {
protected:
- virtual void sendStatistics();
+ RequestGroup* _requestGroup;
public:
- TorrentConsoleDownloadEngine();
- ~TorrentConsoleDownloadEngine();
+ RequestGroupAware(RequestGroup* requestGroup);
- virtual void afterEachIteration();
+ ~RequestGroupAware();
};
-#endif // _D_TORRENT_CONSOLE_DOWNLOAD_ENGINE_H_
+#endif // _D_REQUEST_GROUP_AWARE_H_
diff --git a/src/RequestGroupEntry.cc b/src/RequestGroupEntry.cc
index 980d65b0..cd17e043 100644
--- a/src/RequestGroupEntry.cc
+++ b/src/RequestGroupEntry.cc
@@ -33,12 +33,26 @@
*/
/* copyright --> */
#include "RequestGroupEntry.h"
-#include "DownloadCommand.h"
+#include "RequestGroup.h"
+#include "Command.h"
+
+RequestGroupEntry::RequestGroupEntry(RequestGroup* requestGroup,
+ Command* nextCommand):
+ _requestGroup(requestGroup),
+ _nextCommand(nextCommand)
+{
+ _requestGroup->increaseNumCommand();
+}
RequestGroupEntry::~RequestGroupEntry()
{
- if(_shouldAddNumConnection) {
- --_requestGroup->numConnection;
- }
- delete _nextDownloadCommand;
+ _requestGroup->decreaseNumCommand();
+ delete _nextCommand;
+}
+
+Command* RequestGroupEntry::popNextCommand()
+{
+ Command* temp = _nextCommand;
+ _nextCommand = 0;
+ return temp;
}
diff --git a/src/RequestGroupEntry.h b/src/RequestGroupEntry.h
index 157f3048..812720f7 100644
--- a/src/RequestGroupEntry.h
+++ b/src/RequestGroupEntry.h
@@ -36,74 +36,32 @@
#define _D_REQUEST_GROUP_ENTRY_H_
#include "ProgressAwareEntry.h"
-#include "Request.h"
-#include "RequestGroup.h"
+class RequestGroup;
+class Command;
class DownloadCommand;
-class RequestGroupEntry : public ProgressAwareEntry {
+class RequestGroupEntry {
protected:
- int32_t _cuid;
- RequestHandle _currentRequest;
RequestGroup* _requestGroup;
- DownloadCommand* _nextDownloadCommand;
- bool _shouldAddNumConnection;
+ Command* _nextCommand;
public:
- RequestGroupEntry(int32_t cuid,
- const RequestHandle& currentRequest,
- RequestGroup* requestGroup,
- DownloadCommand* nextDownloadCommand = 0):
- _cuid(cuid),
- _currentRequest(currentRequest),
- _requestGroup(requestGroup),
- _nextDownloadCommand(nextDownloadCommand)
- {
- if(nextDownloadCommand) {
- _shouldAddNumConnection = false;
- } else {
- _shouldAddNumConnection = true;
- ++_requestGroup->numConnection;
- }
- }
+ RequestGroupEntry(RequestGroup* requestGroup,
+ Command* nextCommand = 0);
virtual ~RequestGroupEntry();
- virtual int64_t getTotalLength() const
- {
- return _requestGroup->getTotalLength();
- }
-
- int32_t getCUID() const
- {
- return _cuid;
- }
-
- RequestHandle getCurrentRequest() const
- {
- return _currentRequest;
- }
-
RequestGroup* getRequestGroup() const
{
return _requestGroup;
}
- /*
- void setNextDownloadCommand(DownloadCommand* command)
- {
- _nextDownloadCommand = command;
- }
- */
- DownloadCommand* getNextDownloadCommand() const
- {
- return _nextDownloadCommand;
- }
- DownloadCommand* popNextDownloadCommand()
+ Command* getNextCommand() const
{
- DownloadCommand* temp = _nextDownloadCommand;
- _nextDownloadCommand = 0;
- return temp;
+ return _nextCommand;
}
+
+ Command* popNextCommand();
bool operator==(const RequestGroupEntry& entry) const
{
diff --git a/src/RequestGroupMan.cc b/src/RequestGroupMan.cc
index b1b87713..5d13a845 100644
--- a/src/RequestGroupMan.cc
+++ b/src/RequestGroupMan.cc
@@ -33,9 +33,64 @@
*/
/* copyright --> */
#include "RequestGroupMan.h"
+#include "BtProgressInfoFile.h"
+#include "DlAbortEx.h"
+#include "RequestGroup.h"
+#include "LogFactory.h"
#include "DownloadEngine.h"
#include "message.h"
#include <iomanip>
+#include <sstream>
+
+RequestGroupMan::RequestGroupMan(const RequestGroups& requestGroups,
+ int32_t maxSimultaneousDownloads):
+ _requestGroups(requestGroups),
+ _logger(LogFactory::getInstance()),
+ _maxSimultaneousDownloads(maxSimultaneousDownloads),
+ _gidCounter(0) {}
+
+bool RequestGroupMan::downloadFinished()
+{
+ if(!_reservedGroups.empty()) {
+ return false;
+ }
+ for(RequestGroups::iterator itr = _requestGroups.begin();
+ itr != _requestGroups.end(); ++itr) {
+ if((*itr)->getNumCommand() > 0 || !(*itr)->downloadFinished()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void RequestGroupMan::addRequestGroup(const RequestGroupHandle& group)
+{
+ _requestGroups.push_back(group);
+}
+
+void RequestGroupMan::addReservedGroup(const RequestGroups& groups)
+{
+ _reservedGroups.insert(_reservedGroups.end(), groups.begin(), groups.end());
+}
+
+void RequestGroupMan::addReservedGroup(const RequestGroupHandle& group)
+{
+ _reservedGroups.push_back(group);
+}
+
+int32_t RequestGroupMan::countRequestGroup() const
+{
+ return _requestGroups.size();
+}
+
+RequestGroupHandle RequestGroupMan::getRequestGroup(int32_t index) const
+{
+ if(index < (int32_t)_requestGroups.size()) {
+ return _requestGroups[index];
+ } else {
+ return 0;
+ }
+}
void RequestGroupMan::removeStoppedGroup()
{
@@ -43,18 +98,27 @@ void RequestGroupMan::removeStoppedGroup()
RequestGroups temp;
for(RequestGroups::iterator itr = _requestGroups.begin();
itr != _requestGroups.end(); ++itr) {
- if((*itr)->numConnection > 0) {
+ if((*itr)->getNumCommand() > 0) {
temp.push_back(*itr);
} else {
(*itr)->closeFile();
+ RequestGroups nextGroups = (*itr)->postDownloadProcessing();
+
if((*itr)->downloadFinished()) {
_logger->notice(MSG_FILE_DOWNLOAD_COMPLETED,
(*itr)->getFilePath().c_str());
- (*itr)->remove();
+ (*itr)->getProgressInfoFile()->removeFile();
} else {
- (*itr)->save();
+ try {
+ (*itr)->getProgressInfoFile()->save();
+ } catch(DlAbortEx* ex) {
+ _logger->error(EX_EXCEPTION_CAUGHT, ex);
+ delete ex;
+ }
}
+ (*itr)->releaseRuntimeResource();
++count;
+ _spentGroups.push_back(*itr);
}
}
_requestGroups = temp;
@@ -65,22 +129,28 @@ void RequestGroupMan::removeStoppedGroup()
void RequestGroupMan::fillRequestGroupFromReserver(DownloadEngine* e)
{
+ RequestGroups temp;
removeStoppedGroup();
-
int32_t count = 0;
for(int32_t num = _maxSimultaneousDownloads-_requestGroups.size();
num > 0 && _reservedGroups.size() > 0; --num) {
-
RequestGroupHandle groupToAdd = _reservedGroups.front();
_reservedGroups.pop_front();
-
- _requestGroups.push_back(groupToAdd);
- groupToAdd->initSegmentMan();
- groupToAdd->setGID(++_gidCounter);
- Commands commands = groupToAdd->createNextCommand(e, 1);
- count += commands.size();
- e->addCommand(commands);
+ if(!groupToAdd->isDependencyResolved()) {
+ temp.push_front(groupToAdd);
+ continue;
+ }
+ try {
+ _requestGroups.push_back(groupToAdd);
+ Commands commands = groupToAdd->createInitialCommand(e);
+ ++count;
+ e->addCommand(commands);
+ } catch(DlAbortEx* ex) {
+ _logger->error(EX_EXCEPTION_CAUGHT, ex);
+ delete ex;
+ }
}
+ copy(temp.begin(), temp.end(), front_inserter(_reservedGroups));
if(count > 0) {
_logger->debug("%d RequestGroup(s) added.", count);
}
@@ -89,18 +159,48 @@ void RequestGroupMan::fillRequestGroupFromReserver(DownloadEngine* e)
Commands RequestGroupMan::getInitialCommands(DownloadEngine* e)
{
Commands commands;
- for(RequestGroups::const_iterator itr = _requestGroups.begin();
- itr != _requestGroups.end(); ++itr) {
- (*itr)->initSegmentMan();
- (*itr)->setGID(++_gidCounter);
- Commands nextCommands = (*itr)->createNextCommand(e, 1);
- if(!nextCommands.empty()) {
- commands.push_back(nextCommands.front());
+ for(RequestGroups::iterator itr = _requestGroups.begin();
+ itr != _requestGroups.end();) {
+ if((*itr)->isDependencyResolved()) {
+ try {
+ Commands nextCommands = (*itr)->createInitialCommand(e);
+ copy(nextCommands.begin(), nextCommands.end(), back_inserter(commands));
+ ++itr;
+ } catch(DlAbortEx* e) {
+ _logger->error(EX_EXCEPTION_CAUGHT, e);
+ delete e;
+ }
+ } else {
+ _reservedGroups.push_front((*itr));
+ itr = _requestGroups.erase(itr);
}
}
return commands;
}
+void RequestGroupMan::save()
+{
+ for(RequestGroups::iterator itr = _requestGroups.begin();
+ itr != _requestGroups.end(); ++itr) {
+ if(!(*itr)->downloadFinished()) {
+ try {
+ (*itr)->getProgressInfoFile()->save();
+ } catch(DlAbortEx* e) {
+ _logger->error(EX_EXCEPTION_CAUGHT, e);
+ delete e;
+ }
+ }
+ }
+}
+
+void RequestGroupMan::closeFile()
+{
+ for(RequestGroups::iterator itr = _requestGroups.begin();
+ itr != _requestGroups.end(); ++itr) {
+ (*itr)->closeFile();
+ }
+}
+
void RequestGroupMan::showDownloadResults(ostream& o) const
{
// Download Results:
@@ -110,30 +210,48 @@ void RequestGroupMan::showDownloadResults(ostream& o) const
<<_("Download Results:") << "\n"
<< "idx|stat|path/URI" << "\n"
<< "===+====+======================================================================" << "\n";
+ /*
+ RequestGroups groups(_spentGroups.begin(), _spentGroups.end());
for(RequestGroups::const_iterator itr = _requestGroups.begin();
itr != _requestGroups.end(); ++itr) {
- o << setw(3) << (*itr)->getGID() << "|";
if((*itr)->downloadFinished()) {
- o << "OK ";
- } else {
- o << "ERR ";
+ groups.push_back(*itr);
}
- o << "|";
- if((*itr)->downloadFinished()) {
- o << (*itr)->getFilePath();
- } else {
- Strings uris = (*itr)->getUris();
- if(uris.empty()) {
+ }
+ */
+ for(RequestGroups::const_iterator itr = _spentGroups.begin();
+ itr != _spentGroups.end(); ++itr) {
+ o << formatDownloadResult((*itr)->downloadFinished()?"OK":"ERR", *itr) << "\n";
+ }
+ for(RequestGroups::const_iterator itr = _requestGroups.begin();
+ itr != _requestGroups.end(); ++itr) {
+ o << formatDownloadResult((*itr)->downloadFinished()?"OK":"INPR", *itr) << "\n";
+ }
+}
+
+string RequestGroupMan::formatDownloadResult(const string& status, const RequestGroupHandle& requestGroup) const
+{
+ stringstream o;
+ o << setw(3) << requestGroup->getGID() << "|"
+ << setw(4) << status << "|";
+ if(requestGroup->downloadFinished()) {
+ o << requestGroup->getFilePath();
+ } else {
+ Strings uris = requestGroup->getUris();
+ if(uris.empty()) {
+ if(requestGroup->getFilePath().empty()) {
o << "n/a";
} else {
- o << uris.front();
- if(uris.size() > 1) {
- o << " (" << uris.size()-1 << "more)";
- }
+ o << requestGroup->getFilePath();
+ }
+ } else {
+ o << uris.front();
+ if(uris.size() > 1) {
+ o << " (" << uris.size()-1 << "more)";
}
}
- o << "\n";
}
+ return o.str();
}
bool RequestGroupMan::isSameFileBeingDownloaded(RequestGroup* requestGroup) const
@@ -147,3 +265,21 @@ bool RequestGroupMan::isSameFileBeingDownloaded(RequestGroup* requestGroup) cons
}
return false;
}
+
+void RequestGroupMan::halt()
+{
+ for(RequestGroups::const_iterator itr = _requestGroups.begin();
+ itr != _requestGroups.end(); ++itr) {
+ (*itr)->setHaltRequested(true);
+ }
+}
+
+TransferStat RequestGroupMan::calculateStat()
+{
+ TransferStat stat;
+ for(RequestGroups::const_iterator itr = _requestGroups.begin();
+ itr != _requestGroups.end(); ++itr) {
+ stat = stat+(*itr)->calculateStat();
+ }
+ return stat;
+}
diff --git a/src/RequestGroupMan.h b/src/RequestGroupMan.h
index a78de75e..a533b71c 100644
--- a/src/RequestGroupMan.h
+++ b/src/RequestGroupMan.h
@@ -36,73 +36,37 @@
#define _D_REQUEST_GROUP_MAN_H_
#include "common.h"
-#include "RequestGroup.h"
-#include "LogFactory.h"
+#include "TransferStat.h"
class DownloadEngine;
+class RequestGroup;
+extern typedef SharedHandle<RequestGroup> RequestGroupHandle;
+extern typedef deque<RequestGroupHandle> RequestGroups;
+class Command;
+extern typedef deque<Command*> Commands;
+class Logger;
class RequestGroupMan {
private:
RequestGroups _requestGroups;
RequestGroups _reservedGroups;
+ RequestGroups _spentGroups;
const Logger* _logger;
int32_t _maxSimultaneousDownloads;
int32_t _gidCounter;
+
+ string formatDownloadResult(const string& status, const RequestGroupHandle& requestGroup) const;
+
public:
- RequestGroupMan(const RequestGroups& requestGroups = RequestGroups(), int32_t maxSimultaneousDownloads = 1):
- _requestGroups(requestGroups),
- _logger(LogFactory::getInstance()),
- _maxSimultaneousDownloads(maxSimultaneousDownloads),
- _gidCounter(0) {}
-
- bool downloadFinished()
- {
- for(RequestGroups::iterator itr = _requestGroups.begin();
- itr != _requestGroups.end(); ++itr) {
- if((*itr)->numConnection > 0 || !(*itr)->getSegmentMan()->finished()) {
- return false;
- }
- }
- return true;
- }
-
- void save()
- {
- for(RequestGroups::iterator itr = _requestGroups.begin();
- itr != _requestGroups.end(); ++itr) {
- if(!(*itr)->getSegmentMan()->finished()) {
- (*itr)->getSegmentMan()->save();
- }
- }
- }
-
- void closeFile()
- {
- for(RequestGroups::iterator itr = _requestGroups.begin();
- itr != _requestGroups.end(); ++itr) {
- (*itr)->getSegmentMan()->diskWriter->closeFile();
- }
- }
+ RequestGroupMan(const RequestGroups& requestGroups, int32_t maxSimultaneousDownloads = 1);
+
+ bool downloadFinished();
+
+ void save();
+
+ void closeFile();
- int64_t getDownloadLength() const
- {
- int64_t downloadLength = 0;
- for(RequestGroups::const_iterator itr = _requestGroups.begin();
- itr != _requestGroups.end(); ++itr) {
- downloadLength += (*itr)->getSegmentMan()->getDownloadLength();
- }
- return downloadLength;
- }
-
- int64_t getTotalLength() const
- {
- int64_t totalLength = 0;
- for(RequestGroups::const_iterator itr = _requestGroups.begin();
- itr != _requestGroups.end(); ++itr) {
- totalLength += (*itr)->getSegmentMan()->totalSize;
- }
- return totalLength;
- }
+ void halt();
Commands getInitialCommands(DownloadEngine* e);
@@ -110,48 +74,21 @@ public:
void fillRequestGroupFromReserver(DownloadEngine* e);
- void addRequestGroup(const RequestGroupHandle& group)
- {
- _requestGroups.push_back(group);
- }
-
- void addReservedGroup(const RequestGroups& groups)
- {
- _reservedGroups.insert(_reservedGroups.end(), groups.begin(), groups.end());
- }
-
- void addReservedGroup(const RequestGroupHandle& group)
- {
- _reservedGroups.push_back(group);
- }
-
- int32_t countRequestGroup() const
- {
- return _requestGroups.size();
- }
+ void addRequestGroup(const RequestGroupHandle& group);
+
+ void addReservedGroup(const RequestGroups& groups);
+
+ void addReservedGroup(const RequestGroupHandle& group);
+
+ int32_t countRequestGroup() const;
- RequestGroupHandle getRequestGroup(int32_t index) const
- {
- if(index < (int32_t)_requestGroups.size()) {
- return _requestGroups[index];
- } else {
- return 0;
- }
- }
+ RequestGroupHandle getRequestGroup(int32_t index) const;
void showDownloadResults(ostream& o) const;
- int32_t getErrors() const
- {
- int32_t errors = 0;
- for(RequestGroups::const_iterator itr = _requestGroups.begin();
- itr != _requestGroups.end(); ++itr) {
- errors += (*itr)->getSegmentMan()->errors;
- }
- return errors;
- }
-
bool isSameFileBeingDownloaded(RequestGroup* requestGroup) const;
+
+ TransferStat calculateStat();
};
typedef SharedHandle<RequestGroupMan> RequestGroupManHandle;
diff --git a/src/SeedCheckCommand.cc b/src/SeedCheckCommand.cc
index b419738c..07ac79ee 100644
--- a/src/SeedCheckCommand.cc
+++ b/src/SeedCheckCommand.cc
@@ -36,10 +36,13 @@
#include "message.h"
SeedCheckCommand::SeedCheckCommand(int cuid,
- TorrentDownloadEngine* e,
+ RequestGroup* requestGroup,
+ DownloadEngine* e,
const BtContextHandle& btContext,
SeedCriteriaHandle seedCriteria)
- :BtContextAwareCommand(cuid, btContext),
+ :Command(cuid),
+ BtContextAwareCommand(btContext),
+ RequestGroupAware(requestGroup),
e(e),
seedCriteria(seedCriteria),
checkStarted(false) {}
diff --git a/src/SeedCheckCommand.h b/src/SeedCheckCommand.h
index 4ade4094..8716dad0 100644
--- a/src/SeedCheckCommand.h
+++ b/src/SeedCheckCommand.h
@@ -35,20 +35,26 @@
#ifndef _D_SEED_CHECK_COMMAND_H_
#define _D_SEED_CHECK_COMMAND_H_
+#include "Command.h"
#include "BtContextAwareCommand.h"
-#include "TorrentDownloadEngine.h"
+#include "DownloadEngine.h"
#include "TimeA2.h"
#include "SeedCriteria.h"
+#include "RequestGroupAware.h"
-class SeedCheckCommand : public BtContextAwareCommand {
+class SeedCheckCommand : public Command,
+ public BtContextAwareCommand,
+ public RequestGroupAware
+{
private:
- TorrentDownloadEngine* e;
+ DownloadEngine* e;
Time checkPoint;
SeedCriteriaHandle seedCriteria;
bool checkStarted;
public:
SeedCheckCommand(int cuid,
- TorrentDownloadEngine* e,
+ RequestGroup* requestGroup,
+ DownloadEngine* e,
const BtContextHandle& btContext,
SeedCriteriaHandle seedCriteria);
diff --git a/src/Segment.cc b/src/Segment.cc
index b4881c1e..79f8ce20 100644
--- a/src/Segment.cc
+++ b/src/Segment.cc
@@ -36,9 +36,13 @@
#include "Segment.h"
ostream& operator<<(ostream& o, const Segment& segment) {
- o << "index = " << segment.index << ", ";
- o << "length = " << segment.length << ", ";
- o << "segmentLength = " << segment.segmentLength << ", ";
- o << "writtenLength = " << segment.writtenLength;
+ o << "index = " << segment._piece->getIndex() << ", ";
+ o << "length = " << segment._piece->getLength() << ", ";
+ o << "segmentLength = " << segment._pieceLength << ", ";
+ if(segment.complete()) {
+ o << "writtenLength = " << segment._piece->getLength();
+ } else {
+ o << "writtenLength = " << (segment._piece->getMissingUnusedBlockIndex()-1)*BLOCK_LENGTH;
+ }
return o;
}
diff --git a/src/Segment.h b/src/Segment.h
index d082fbc1..00d05b89 100644
--- a/src/Segment.h
+++ b/src/Segment.h
@@ -36,56 +36,35 @@
#define _D_SEGMENT_H_
#include "common.h"
-#include <deque>
-using namespace std;
+class Piece;
+extern typedef SharedHandle<Piece> PieceHandle;
class Segment {
public:
- int32_t index;
- int32_t length;
- int32_t segmentLength;
- int32_t writtenLength;
+ virtual ~Segment() {}
- Segment(int32_t index, int32_t length, int32_t segmentLength, int32_t writtenLength = 0)
- :index(index), length(length), segmentLength(segmentLength),
- writtenLength(writtenLength) {}
+ virtual bool complete() const = 0;
- Segment():index(-1), length(0), segmentLength(0), writtenLength(0) {}
+ virtual int32_t getIndex() const = 0;
- bool complete() const {
- return length <= writtenLength;
- }
+ virtual int64_t getPosition() const = 0;
+
+ virtual int64_t getPositionToWrite() const = 0;
- bool isNull() const {
- return index == -1;
- }
+ virtual int32_t getLength() const = 0;
- int64_t getPosition() const {
- return ((int64_t)index)*segmentLength;
- }
+ virtual int32_t getSegmentLength() const = 0;
- int64_t getPositionToWrite() const
- {
- return getPosition()+writtenLength;
- }
+ virtual int32_t getWrittenLength() const = 0;
- bool operator==(const Segment& segment) const {
- return index == segment.index &&
- length == segment.length &&
- segmentLength == segment.segmentLength &&
- writtenLength == segment.writtenLength;
- }
+ virtual int32_t getOverflowLength() const = 0;
- bool operator!=(const Segment& segment) const {
- return !(*this == segment);
- }
+ virtual void updateWrittenLength(int32_t bytes) = 0;
- friend ostream& operator<<(ostream& o, const Segment& segment);
+ virtual PieceHandle getPiece() const = 0;
};
-ostream& operator<<(ostream& o, const Segment& segment);
-
typedef SharedHandle<Segment> SegmentHandle;
#endif // _D_SEGMENT_H_
diff --git a/src/SegmentMan.cc b/src/SegmentMan.cc
index 0240bc2d..9ae96d7a 100644
--- a/src/SegmentMan.cc
+++ b/src/SegmentMan.cc
@@ -38,244 +38,95 @@
#include "File.h"
#include "message.h"
#include "prefs.h"
+#include "PiecedSegment.h"
+#include "GrowSegment.h"
+#include "DiskAdaptor.h"
#include "LogFactory.h"
-#include "BitfieldManFactory.h"
+#include "PieceStorage.h"
+#include "PeerStat.h"
+#include "Option.h"
+#include "DownloadContext.h"
+#include "Piece.h"
#ifdef ENABLE_MESSAGE_DIGEST
#include "MessageDigestHelper.h"
#endif // ENABLE_MESSAGE_DIGEST
#include "a2io.h"
#include <errno.h>
-SegmentMan::SegmentMan():logger(LogFactory::getInstance()),
- bitfield(0),
- totalSize(0),
- isSplittable(true),
- downloadStarted(false),
- dir("."),
- errors(0),
- diskWriter(0)
+SegmentEntry::SegmentEntry(int32_t cuid, const SegmentHandle& segment):
+ cuid(cuid), segment(segment) {}
+
+SegmentEntry::~SegmentEntry() {}
+
+SegmentMan::SegmentMan(const Option* option,
+ const DownloadContextHandle& downloadContext,
+ const PieceStorageHandle& pieceStorage):
+ _option(option),
+ logger(LogFactory::getInstance()),
+ _downloadContext(downloadContext),
+ _pieceStorage(pieceStorage)
{}
-SegmentMan::~SegmentMan() {
- delete bitfield;
-}
+SegmentMan::~SegmentMan() {}
-bool SegmentMan::segmentFileExists() const {
- if(!isSplittable) {
+bool SegmentMan::downloadFinished() const
+{
+ if(_pieceStorage.isNull()) {
return false;
- }
- string segFilename = getSegmentFilePath();
- File f(segFilename);
- if(f.isFile()) {
- logger->info(MSG_SEGMENT_FILE_EXISTS, segFilename.c_str());
- return true;
} else {
- logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, segFilename.c_str());
- return false;
- }
-}
-
-void SegmentMan::load() {
- if(!isSplittable) {
- return;
- }
- string segFilename = getSegmentFilePath();
- logger->info(MSG_LOADING_SEGMENT_FILE, segFilename.c_str());
- FILE* segFile = openSegFile(segFilename, "r+b");
- try {
- read(segFile);
- fclose(segFile);
- } catch(string ex) {
- fclose(segFile);
- throw new DlAbortEx(EX_SEGMENT_FILE_READ,
- segFilename.c_str(), strerror(errno));
- }
- logger->info(MSG_LOADED_SEGMENT_FILE);
-}
-
-void SegmentMan::save() const {
- if(!isSplittable || totalSize == 0 || !bitfield) {
- return;
- }
- string segFilename = getSegmentFilePath();
- logger->info(MSG_SAVING_SEGMENT_FILE, segFilename.c_str());
-
- string segFilenameTemp = segFilename+"__temp";
- FILE* segFile = openSegFile(segFilenameTemp, "wb");
- try {
- if(fwrite(&totalSize, sizeof(totalSize), 1, segFile) < 1) {
- throw string("writeError");
- }
- int32_t segmentLength = bitfield->getBlockLength();
- if(fwrite(&segmentLength, sizeof(segmentLength), 1, segFile) < 1) {
- throw string("writeError");
- }
- if(bitfield) {
- int32_t bitfieldLength = bitfield->getBitfieldLength();
- if(fwrite(&bitfieldLength, sizeof(bitfieldLength), 1, segFile) < 1) {
- throw string("writeError");
- }
- if(fwrite(bitfield->getBitfield(), bitfield->getBitfieldLength(),
- 1, segFile) < 1) {
- throw string("writeError");
- }
- } else {
- int32_t i = 0;
- if(fwrite(&i, sizeof(i), 1, segFile) < 1) {
- throw string("writeError");
- }
- }
- int32_t usedSegmentCount = usedSegmentEntries.size();
- if(fwrite(&usedSegmentCount, sizeof(usedSegmentCount), 1, segFile) < 1) {
- throw string("writeError");
- }
- for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
- itr != usedSegmentEntries.end(); itr++) {
- if(fwrite((*itr)->segment.get(), sizeof(Segment), 1, segFile) < 1) {
- throw string("writeError");
- }
- }
- fclose(segFile);
- logger->info(MSG_SAVED_SEGMENT_FILE);
- } catch(string ex) {
- fclose(segFile);
- throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
- segFilename.c_str(), strerror(errno));
- }
-
- if(rename(segFilenameTemp.c_str(), segFilename.c_str()) == -1) {
- throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
- segFilename.c_str(), strerror(errno));
+ return _pieceStorage->downloadFinished();
}
}
-FILE* SegmentMan::openSegFile(const string& segFilename, const string& mode) const {
- FILE* segFile = fopen(segFilename.c_str(), mode.c_str());
- if(segFile == NULL) {
- throw new DlAbortEx(EX_SEGMENT_FILE_OPEN,
- segFilename.c_str(), strerror(errno));
- }
- return segFile;
+void SegmentMan::init()
+{
+ // TODO Do we have to do something about DownloadContext and PieceStorage here?
}
-void SegmentMan::read(FILE* file) {
- assert(file != NULL);
- if(fread(&totalSize, sizeof(totalSize), 1, file) < 1) {
- throw string("readError");
- }
- int32_t segmentSize;
- if(fread(&segmentSize, sizeof(segmentSize), 1, file) < 1) {
- throw string("readError");
- }
- int32_t bitfieldLength;
- if(fread(&bitfieldLength, sizeof(bitfieldLength), 1, file) < 1) {
- throw string("readError");
- }
- if(bitfieldLength > 0) {
- initBitfield(segmentSize, totalSize);
- unsigned char* savedBitfield = new unsigned char[bitfield->getBitfieldLength()];
- if(fread(savedBitfield, bitfield->getBitfieldLength(), 1, file) < 1) {
- delete [] savedBitfield;
- throw string("readError");
- } else {
- bitfield->setBitfield(savedBitfield, bitfield->getBitfieldLength());
- delete [] savedBitfield;
- }
- }
- int32_t segmentCount;
- if(fread(&segmentCount, sizeof(segmentCount), 1, file) < 1) {
- throw string("readError");
- }
- while(segmentCount--) {
- SegmentHandle seg;
- if(fread(seg.get(), sizeof(Segment), 1, file) < 1) {
- throw string("readError");
- }
- usedSegmentEntries.push_back(SegmentEntryHandle(new SegmentEntry(0, seg)));
+int64_t SegmentMan::getTotalLength() const
+{
+ if(_pieceStorage.isNull()) {
+ return 0;
+ } else {
+ return _pieceStorage->getTotalLength();
}
}
-void SegmentMan::remove() const {
- if(!isSplittable) {
- return;
- }
- if(segmentFileExists()) {
- File f(getSegmentFilePath());
- f.remove();
- }
+void SegmentMan::setPieceStorage(const PieceStorageHandle& pieceStorage)
+{
+ _pieceStorage = pieceStorage;
}
-bool SegmentMan::finished() const {
- if(!downloadStarted) {
- return false;
- }
- if(!bitfield) {
- return false;
- }
- assert(bitfield);
- return bitfield->isAllBitSet();
+void SegmentMan::setDownloadContext(const DownloadContextHandle& downloadContext)
+{
+ _downloadContext = downloadContext;
}
-void SegmentMan::removeIfFinished() const {
- if(finished()) {
- remove();
+SegmentHandle SegmentMan::checkoutSegment(int32_t cuid,
+ const PieceHandle& piece)
+{
+ if(piece.isNull()) {
+ return 0;
}
-}
+ logger->debug("Attach segment#%d to CUID#%d.", piece->getIndex(), cuid);
-void SegmentMan::init() {
- totalSize = 0;
- isSplittable = false;
- downloadStarted = false;
- errors = 0;
- //segments.clear();
- usedSegmentEntries.clear();
- delete bitfield;
- bitfield = 0;
- peerStats.clear();
- diskWriter->closeFile();
-
-}
-
-void SegmentMan::initBitfield(int32_t segmentLength, int64_t totalLength) {
- delete bitfield;
- this->bitfield = BitfieldManFactory::getFactoryInstance()->createBitfieldMan(segmentLength, totalLength);
-}
-
-SegmentHandle SegmentMan::checkoutSegment(int32_t cuid, int32_t index) {
- logger->debug("Attach segment#%d to CUID#%d.", index, cuid);
- bitfield->setUseBit(index);
- SegmentEntryHandle segmentEntry = getSegmentEntryByIndex(index);
- SegmentHandle segment(0);
- if(segmentEntry.isNull()) {
- segment = new Segment(index, bitfield->getBlockLength(index),
- bitfield->getBlockLength());
- SegmentEntryHandle entry = new SegmentEntry(cuid, segment);
- usedSegmentEntries.push_back(entry);
+ SegmentHandle segment = 0;
+ if(piece->getLength() == 0) {
+ segment = new GrowSegment(piece);
} else {
- segmentEntry->cuid = cuid;
- segment = segmentEntry->segment;
+ segment = new PiecedSegment(_downloadContext->getPieceLength(), piece);
}
+ SegmentEntryHandle entry = new SegmentEntry(cuid, segment);
+ usedSegmentEntries.push_back(entry);
+
logger->debug("index=%d, length=%d, segmentLength=%d, writtenLength=%d",
- segment->index, segment->length, segment->segmentLength,
- segment->writtenLength);
+ segment->getIndex(),
+ segment->getLength(),
+ segment->getSegmentLength(),
+ segment->getWrittenLength());
return segment;
}
-SegmentHandle SegmentMan::onNullBitfield(int32_t cuid) {
- if(usedSegmentEntries.size() == 0) {
- SegmentHandle segment = new Segment(0, 0, 0);
- usedSegmentEntries.push_back(SegmentEntryHandle(new SegmentEntry(cuid, segment)));
- return segment;
- } else {
- SegmentEntryHandle segmentEntry = getSegmentEntryByCuid(cuid);
- if(segmentEntry.isNull()) {
- return 0;
- } else {
- return segmentEntry->segment;
- }
- }
-}
-
SegmentEntryHandle SegmentMan::findSlowerSegmentEntry(const PeerStatHandle& peerStat) const {
int32_t speed = (int32_t)(peerStat->getAvgDownloadSpeed()*0.8);
SegmentEntryHandle slowSegmentEntry(0);
@@ -288,7 +139,7 @@ SegmentEntryHandle SegmentMan::findSlowerSegmentEntry(const PeerStatHandle& peer
PeerStatHandle p = getPeerStat(segmentEntry->cuid);
if(!p.get() || p->getCuid() == peerStat->getCuid() ||
p->getStatus() != PeerStat::ACTIVE ||
- !p->getDownloadStartTime().elapsed(option->getAsInt(PREF_STARTUP_IDLE_TIME))) {
+ !p->getDownloadStartTime().elapsed(_option->getAsInt(PREF_STARTUP_IDLE_TIME))) {
continue;
}
int32_t pSpeed = p->calculateDownloadSpeed();
@@ -301,91 +152,55 @@ SegmentEntryHandle SegmentMan::findSlowerSegmentEntry(const PeerStatHandle& peer
}
SegmentHandle SegmentMan::getSegment(int32_t cuid) {
- if(!bitfield) {
- return onNullBitfield(cuid);
- }
SegmentEntryHandle segmentEntry = getSegmentEntryByCuid(cuid);
if(!segmentEntry.isNull()) {
return segmentEntry->segment;
}
- int32_t index = bitfield->getSparseMissingUnusedIndex();
- if(index == -1) {
+ PieceHandle piece = _pieceStorage->getMissingPiece();
+ if(piece.isNull()) {
PeerStatHandle myPeerStat = getPeerStat(cuid);
- if(!myPeerStat.get()) {
+ if(myPeerStat.isNull()) {
return 0;
}
SegmentEntryHandle slowSegmentEntry = findSlowerSegmentEntry(myPeerStat);
if(slowSegmentEntry.get()) {
logger->info(MSG_SEGMENT_FORWARDING,
slowSegmentEntry->cuid,
- slowSegmentEntry->segment->index,
+ slowSegmentEntry->segment->getIndex(),
cuid);
PeerStatHandle slowPeerStat = getPeerStat(slowSegmentEntry->cuid);
slowPeerStat->requestIdle();
cancelSegment(slowSegmentEntry->cuid);
- return checkoutSegment(cuid, slowSegmentEntry->segment->index);
+ return checkoutSegment(cuid, slowSegmentEntry->segment->getPiece());
} else {
return 0;
}
} else {
- return checkoutSegment(cuid, index);
+ return checkoutSegment(cuid, piece);
}
}
SegmentHandle SegmentMan::getSegment(int32_t cuid, int32_t index) {
- if(!bitfield) {
- return onNullBitfield(cuid);
- }
- if(index < 0 || (int32_t)bitfield->countBlock() <= index) {
+ if(index < 0 || _downloadContext->getNumPieces() <= index) {
return 0;
}
- if(bitfield->isBitSet(index) || bitfield->isUseBitSet(index)) {
- return 0;
- } else {
- return checkoutSegment(cuid, index);
- }
-}
-/*
-bool SegmentMan::updateSegment(int cuid, const Segment& segment) {
- if(segment.isNull()) {
- return false;
- }
- SegmentEntryHandle segmentEntry = getSegmentEntryByCuid(cuid);
- if(segmentEntry.isNull()) {
- return false;
- } else {
- segmentEntry->segment = segment;
- return true;
- }
+ return checkoutSegment(cuid, _pieceStorage->getMissingPiece(index));
}
-*/
void SegmentMan::cancelSegment(int32_t cuid) {
- if(bitfield) {
- for(SegmentEntries::iterator itr = usedSegmentEntries.begin();
- itr != usedSegmentEntries.end(); ++itr) {
- if((*itr)->cuid == cuid) {
- bitfield->unsetUseBit((*itr)->segment->index);
- (*itr)->cuid = 0;
- break;
- }
+ for(SegmentEntries::iterator itr = usedSegmentEntries.begin();
+ itr != usedSegmentEntries.end(); ++itr) {
+ if((*itr)->cuid == cuid) {
+ _pieceStorage->cancelPiece((*itr)->segment->getPiece());
+ usedSegmentEntries.erase(itr);
+ break;
}
- } else {
- usedSegmentEntries.clear();
}
}
bool SegmentMan::completeSegment(int32_t cuid, const SegmentHandle& segment) {
- if(segment->isNull()) {
- return false;
- }
- if(bitfield) {
- bitfield->unsetUseBit(segment->index);
- bitfield->setBit(segment->index);
- } else {
- initBitfield(option->getAsInt(PREF_SEGMENT_SIZE), segment->writtenLength);
- bitfield->setAllBit();
- }
+ _pieceStorage->completePiece(segment->getPiece());
+ _pieceStorage->advertisePiece(cuid, segment->getPiece()->getIndex());
SegmentEntries::iterator itr = getSegmentEntryIteratorByCuid(cuid);
if(itr == usedSegmentEntries.end()) {
return false;
@@ -396,23 +211,15 @@ bool SegmentMan::completeSegment(int32_t cuid, const SegmentHandle& segment) {
}
bool SegmentMan::hasSegment(int32_t index) const {
- if(bitfield) {
- return bitfield->isBitSet(index);
- } else {
- return false;
- }
+ return _pieceStorage->hasPiece(index);
}
int64_t SegmentMan::getDownloadLength() const {
- int64_t dlLength = 0;
- if(bitfield) {
- dlLength += bitfield->getCompletedLength();
- }
- for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
- itr != usedSegmentEntries.end(); itr++) {
- dlLength += (*itr)->segment->writtenLength;
+ if(_pieceStorage.isNull()) {
+ return 0;
+ } else {
+ return _pieceStorage->getCompletedLength();
}
- return dlLength;
}
void SegmentMan::registerPeerStat(const PeerStatHandle& peerStat) {
@@ -422,6 +229,17 @@ void SegmentMan::registerPeerStat(const PeerStatHandle& peerStat) {
}
}
+PeerStatHandle SegmentMan::getPeerStat(int32_t cuid) const
+{
+ for(PeerStats::const_iterator itr = peerStats.begin(); itr != peerStats.end(); ++itr) {
+ const PeerStatHandle& peerStat = *itr;
+ if(peerStat->getCuid() == cuid) {
+ return peerStat;
+ }
+ }
+ return 0;
+}
+
int32_t SegmentMan::calculateDownloadSpeed() const {
int32_t speed = 0;
for(PeerStats::const_iterator itr = peerStats.begin();
@@ -434,19 +252,15 @@ int32_t SegmentMan::calculateDownloadSpeed() const {
return speed;
}
-bool SegmentMan::fileExists() const {
- return File(getFilePath()).exists();
-}
-
void SegmentMan::markAllPiecesDone()
{
- if(bitfield) {
- bitfield->setAllBit();
- }
+ _pieceStorage->markAllPiecesDone();
}
void SegmentMan::markPieceDone(int64_t length)
{
+ // TODO implement this function later
+ /*
if(bitfield) {
if(length == bitfield->getTotalLength()) {
bitfield->setAllBit();
@@ -465,18 +279,45 @@ void SegmentMan::markPieceDone(int64_t length)
}
}
}
+ */
}
#ifdef ENABLE_MESSAGE_DIGEST
+void SegmentMan::validatePieceHash(const SegmentHandle& segment,
+ const string& expectedPieceHash)
+{
+ string actualPieceHash =
+ MessageDigestHelper::digest("sha1",
+ _pieceStorage->getDiskAdaptor(),
+ segment->getPosition(),
+ segment->getLength());
+ if(actualPieceHash == expectedPieceHash) {
+ logger->info(MSG_GOOD_CHUNK_CHECKSUM, actualPieceHash.c_str());
+ } else {
+ _pieceStorage->markPieceMissing(segment->getIndex());
+ logger->info(EX_INVALID_CHUNK_CHECKSUM,
+ segment->getIndex(),
+ Util::llitos(segment->getPosition(), true).c_str(),
+ expectedPieceHash.c_str(),
+ actualPieceHash.c_str());
+ }
+}
+
+/*
bool SegmentMan::isChunkChecksumValidationReady(const ChunkChecksumHandle& chunkChecksum) const {
- return !chunkChecksum.isNull() && bitfield && totalSize > 0 &&
+ return false;
+ // TODO fix this
+ return !chunkChecksum.isNull() && !_downloadContext.isNull() && totalSize > 0 &&
chunkChecksum->getEstimatedDataLength() >= totalSize;
}
+*/
#endif // ENABLE_MESSAGE_DIGEST
#ifdef ENABLE_MESSAGE_DIGEST
+ /*
void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment, const ChunkChecksumHandle& chunkChecksum)
{
+ // TODO implement this function later
if(!isChunkChecksumValidationReady(chunkChecksum)) {
return;
}
@@ -528,4 +369,41 @@ void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment, const
}
}
}
+ */
#endif // ENABLE_MESSAGE_DIGEST
+
+SegmentEntryHandle SegmentMan::getSegmentEntryByIndex(int32_t index)
+{
+ for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
+ itr != usedSegmentEntries.end(); ++itr) {
+ const SegmentEntryHandle& segmentEntry = *itr;
+ if(segmentEntry->segment->getIndex() == index) {
+ return segmentEntry;
+ }
+ }
+ return 0;
+}
+
+SegmentEntryHandle SegmentMan::getSegmentEntryByCuid(int32_t cuid)
+{
+ for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
+ itr != usedSegmentEntries.end(); ++itr) {
+ const SegmentEntryHandle& segmentEntry = *itr;
+ if(segmentEntry->cuid == cuid) {
+ return segmentEntry;
+ }
+ }
+ return 0;
+}
+
+SegmentEntries::iterator SegmentMan::getSegmentEntryIteratorByCuid(int32_t cuid)
+{
+ for(SegmentEntries::iterator itr = usedSegmentEntries.begin();
+ itr != usedSegmentEntries.end(); ++itr) {
+ const SegmentEntryHandle& segmentEntry = *itr;
+ if(segmentEntry->cuid == cuid) {
+ return itr;
+ }
+ }
+ return usedSegmentEntries.end();
+}
diff --git a/src/SegmentMan.h b/src/SegmentMan.h
index fc67214a..41430c22 100644
--- a/src/SegmentMan.h
+++ b/src/SegmentMan.h
@@ -36,18 +36,20 @@
#define _D_SEGMENT_MAN_H_
#include "common.h"
-#include "Logger.h"
-#include "Segment.h"
-#include "Option.h"
-#include "DiskWriter.h"
-#include "Request.h"
-#include "BitfieldMan.h"
-#include "PeerStat.h"
-#ifdef ENABLE_MESSAGE_DIGEST
-# include "ChunkChecksum.h"
-#endif // ENABLE_MESSAGE_DIGEST
-using namespace std;
+class Segment;
+extern typedef SharedHandle<Segment> SegmentHandle;
+class Logger;
+class Option;
+class PeerStat;
+extern typedef SharedHandle<PeerStat> PeerStatHandle;
+typedef deque<PeerStatHandle> PeerStats;
+class DownloadContext;
+extern typedef SharedHandle<DownloadContext> DownloadContextHandle;
+class PieceStorage;
+extern typedef SharedHandle<PieceStorage> PieceStorageHandle;
+class Piece;
+extern typedef SharedHandle<Piece> PieceHandle;
#define SEGMENT_FILE_EXTENSION ".aria2"
@@ -56,162 +58,67 @@ public:
int32_t cuid;
SegmentHandle segment;
public:
- SegmentEntry(int32_t cuid, const SegmentHandle& segment)
- :cuid(cuid), segment(segment) {}
- ~SegmentEntry() {}
+ SegmentEntry(int32_t cuid, const SegmentHandle& segment);
+
+ ~SegmentEntry();
};
typedef SharedHandle<SegmentEntry> SegmentEntryHandle;
typedef deque<SegmentEntryHandle> SegmentEntries;
-typedef deque<PeerStatHandle> PeerStats;
/**
* This class holds the download progress of the one download entry.
*/
class SegmentMan {
private:
+ const Option* _option;
+
const Logger* logger;
- BitfieldMan* bitfield;
+
+ DownloadContextHandle _downloadContext;
+
+ PieceStorageHandle _pieceStorage;
+
SegmentEntries usedSegmentEntries;
+
PeerStats peerStats;
- void read(FILE* file);
- FILE* openSegFile(const string& segFilename, const string& mode) const;
- SegmentHandle onNullBitfield(int32_t cuid);
- SegmentHandle checkoutSegment(int32_t cuid, int32_t index);
+ SegmentHandle checkoutSegment(int32_t cuid, const PieceHandle& piece);
+
SegmentEntryHandle findSlowerSegmentEntry(const PeerStatHandle& peerStat) const;
- SegmentEntryHandle getSegmentEntryByIndex(int32_t index) {
- for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
- itr != usedSegmentEntries.end(); ++itr) {
- const SegmentEntryHandle& segmentEntry = *itr;
- if(segmentEntry->segment->index == index) {
- return segmentEntry;
- }
- }
- return 0;
- }
+
+ SegmentEntryHandle getSegmentEntryByIndex(int32_t index);
- SegmentEntryHandle getSegmentEntryByCuid(int32_t cuid) {
- for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
- itr != usedSegmentEntries.end(); ++itr) {
- const SegmentEntryHandle& segmentEntry = *itr;
- if(segmentEntry->cuid == cuid) {
- return segmentEntry;
- }
- }
- return 0;
- }
-
- SegmentEntries::iterator getSegmentEntryIteratorByCuid(int32_t cuid) {
- for(SegmentEntries::iterator itr = usedSegmentEntries.begin();
- itr != usedSegmentEntries.end(); ++itr) {
- const SegmentEntryHandle& segmentEntry = *itr;
- if(segmentEntry->cuid == cuid) {
- return itr;
- }
- }
- return usedSegmentEntries.end();
- }
+ SegmentEntryHandle getSegmentEntryByCuid(int32_t cuid);
+
+ SegmentEntries::iterator getSegmentEntryIteratorByCuid(int32_t cuid);
public:
- /**
- * The total number of bytes to download.
- * If Transfer-Encoding is Chunked or Content-Length header is not provided,
- * then this value is set to be 0.
- */
- int64_t totalSize;
- /**
- * Represents whether this download is splittable.
- * In Split download(or segmented download), http client establishes
- * more than one connections to the server, and downloads sevral parts of
- * a file at the same time. This boosts download speed.
- * This value is true by default. If total number of bytes is not known or
- * Chunked transfer encoding is used, then this value is set to be 0 by
- * DownloadCommand class.
- */
- bool isSplittable;
- /**
- * Represents whether the download is start or not.
- * The default value is false.
- */
- bool downloadStarted;
- /**
- * Respresents the file name of the downloaded file.
- * If the URL does not contain file name part(http://www.rednoah.com/, for
- * example), this value may be 0 length string.
- * The default value is 0 length string.
- */
- string filename;
- /**
- * directory to store a file
- */
- string dir;
- /**
- * User defined file name for downloaded content
- */
- string ufilename;
+ SegmentMan(const Option* option,
+ const DownloadContextHandle& downloadContext = 0,
+ const PieceStorageHandle& pieceStorage = 0);
- /**
- * Represents the number of failures(usually, DlAbortEx) in downloads.
- */
- int32_t errors;
+ ~SegmentMan();
- const Option* option;
- DiskWriterHandle diskWriter;
- Requests reserved;
- SegmentMan();
- ~SegmentMan();
-
// Initializes totalSize, isSplittable, downloadStarted, errors.
// Clears command queue. Also, closes diskWriter.
void init();
/**
- * Returns dir+"/"+filename.
- * If filename is empty, then returns dir+"/"+"inex.html";
+ * The total number of bytes to download.
+ * If Transfer-Encoding is Chunked or Content-Length header is not provided,
+ * then this value is set to be 0.
*/
- string getFilePath() const {
- return (dir == "" ? "." : dir)+"/"+
- (ufilename == "" ?
- (filename == "" ? "index.html" : filename) : ufilename);
- }
-
- string getSegmentFilePath() const {
- return getFilePath()+SEGMENT_FILE_EXTENSION;
- }
+ int64_t getTotalLength() const;
/**
- * Returns true only if the segment data file exists.
- * The file name of the segment data is filename appended by ".aria2".
- * If isSplittable is false, then returns simply false without any operation.
- */
- bool segmentFileExists() const;
- /**
- * Loads the segment data file.
- * If isSplittable is false, then returns without any operation.
- */
- void load();
- /**
- * Saves the segment data file.
- * If isSplittable is false, then returns without any operation.
- */
- void save() const;
- /**
- * Removes the segment data file.
- * If isSplittable is false, then returns without any operation.
- */
- void remove() const;
- /**
* Returs true when the download has finished.
* If downloadStarted is false or the number of the segments of this object
* holds is 0, then returns false.
*/
- bool finished() const;
- /**
- * if finished() is true, then call remove()
- */
- void removeIfFinished() const;
+ bool downloadFinished() const;
+
/**
* Returns a vacant segment.
* If there is no vacant segment, then returns a segment instance whose
@@ -238,14 +145,17 @@ public:
* Tells SegmentMan that the segment has been downloaded successfully.
*/
bool completeSegment(int32_t cuid, const SegmentHandle& segment);
+
+ /**
+ * Injects PieceStorage.
+ */
+ void setPieceStorage(const PieceStorageHandle& pieceStorage);
+
/**
- * Initializes bitfield with the provided length parameters.
+ * Injects DownloadContext.
*/
- void initBitfield(int32_t segmentLength, int64_t totalLength);
- BitfieldMan* getBitfield() const
- {
- return bitfield;
- }
+ void setDownloadContext(const DownloadContextHandle& downloadContext);
+
/**
* Returns true if the segment whose index is index has been downloaded.
*/
@@ -265,39 +175,25 @@ public:
* Returns peerStat whose cuid is given cuid. If it is not found, returns
* 0.
*/
- PeerStatHandle getPeerStat(int32_t cuid) const {
- for(PeerStats::const_iterator itr = peerStats.begin(); itr != peerStats.end(); ++itr) {
- const PeerStatHandle& peerStat = *itr;
- if(peerStat->getCuid() == cuid) {
- return peerStat;
- }
- }
- return 0;
- }
+ PeerStatHandle getPeerStat(int32_t cuid) const;
/**
* Returns current download speed in bytes per sec.
*/
int32_t calculateDownloadSpeed() const;
- bool fileExists() const;
-
void markAllPiecesDone();
void markPieceDone(int64_t length);
- /**
- * This function must be called when none of segment entries is used.
- */
- void purgeSegmentEntry()
- {
- usedSegmentEntries.clear();
- }
-
#ifdef ENABLE_MESSAGE_DIGEST
+
+ void validatePieceHash(const SegmentHandle& segment, const string& pieceHash);
+ /*
void tryChunkChecksumValidation(const SegmentHandle& segment, const ChunkChecksumHandle& chunkChecksum);
bool isChunkChecksumValidationReady(const ChunkChecksumHandle& chunkChecksum) const;
+ */
#endif // ENABLE_MESSAGE_DIGEST
};
diff --git a/src/SegmentManFactory.h b/src/SegmentManFactory.h
index 4e601926..75754a86 100644
--- a/src/SegmentManFactory.h
+++ b/src/SegmentManFactory.h
@@ -42,7 +42,8 @@ class SegmentManFactory {
public:
virtual ~SegmentManFactory() {}
- virtual SegmentManHandle createNewInstance() = 0;
+ virtual SegmentManHandle createNewInstance(const DownloadContextHandle& dc,
+ const PieceStorageHandle& ps) = 0;
};
typedef SharedHandle<SegmentManFactory> SegmentManFactoryHandle;
diff --git a/src/SingleFileAllocationIterator.cc b/src/SingleFileAllocationIterator.cc
new file mode 100644
index 00000000..1384c163
--- /dev/null
+++ b/src/SingleFileAllocationIterator.cc
@@ -0,0 +1,67 @@
+/* <!-- 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 "SingleFileAllocationIterator.h"
+#include "AbstractSingleDiskAdaptor.h"
+
+#define BUFSIZE 16*1024
+
+SingleFileAllocationIterator::SingleFileAllocationIterator(AbstractSingleDiskAdaptor* diskAdaptor):_diskAdaptor(diskAdaptor), _offset(diskAdaptor->size()) {}
+
+SingleFileAllocationIterator::~SingleFileAllocationIterator() {}
+
+void SingleFileAllocationIterator::allocateChunk()
+{
+ int32_t bufSize = BUFSIZE;
+ unsigned char buf[BUFSIZE];
+ memset(buf, 0, bufSize);
+
+ _diskAdaptor->writeData(buf, bufSize, _offset);
+ _offset += bufSize;
+
+ if(_diskAdaptor->getTotalLength() < _offset) {
+ _diskAdaptor->truncate(getTotalLength());
+ _offset = getTotalLength();
+ }
+}
+
+bool SingleFileAllocationIterator::finished()
+{
+ return getCurrentLength() >= getTotalLength();
+}
+
+int64_t SingleFileAllocationIterator::getTotalLength()
+{
+ return _diskAdaptor->getTotalLength();
+}
diff --git a/src/SingleFileAllocationIterator.h b/src/SingleFileAllocationIterator.h
new file mode 100644
index 00000000..4b401f13
--- /dev/null
+++ b/src/SingleFileAllocationIterator.h
@@ -0,0 +1,66 @@
+/* <!-- 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_SINGLE_FILE_ALLOCATION_ITERATOR_H_
+#define _D_SINGLE_FILE_ALLOCATION_ITERATOR_H_
+
+#include "FileAllocationIterator.h"
+
+class AbstractSingleDiskAdaptor;
+
+class SingleFileAllocationIterator:public FileAllocationIterator
+{
+private:
+ AbstractSingleDiskAdaptor* _diskAdaptor;
+ int64_t _offset;
+public:
+ SingleFileAllocationIterator(AbstractSingleDiskAdaptor* diskAdaptor);
+
+ virtual ~SingleFileAllocationIterator();
+
+ virtual void allocateChunk();
+
+ virtual bool finished();
+
+ virtual int64_t getCurrentLength()
+ {
+ return _offset;
+ }
+
+ virtual int64_t getTotalLength();
+};
+
+typedef SharedHandle<SingleFileAllocationIterator> SingleFileAllocationIteratorHandle;
+
+#endif // _D_SINGLE_FILE_ALLOCATION_ITERATOR_H_
diff --git a/src/SingleFileDownloadContext.h b/src/SingleFileDownloadContext.h
new file mode 100644
index 00000000..f980fb5e
--- /dev/null
+++ b/src/SingleFileDownloadContext.h
@@ -0,0 +1,165 @@
+/* <!-- 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_SINGLE_FILE_DOWNLOAD_CONTEXT_H_
+#define _D_SINGLE_FILE_DOWNLOAD_CONTEXT_H_
+
+#include "DownloadContext.h"
+
+class SingleFileDownloadContext:public DownloadContext
+{
+private:
+ int32_t _pieceLength;
+ /**
+ * Actual file path is _dir + _filename.
+ * If _ufilename is not zero-length string, then _dir + _ufilename.
+ */
+ FileEntryHandle _fileEntry;
+ string _filename;
+ string _ufilename;
+
+ Strings _pieceHashes;
+ string _pieceHashAlgo;
+
+ void updateFileEntry()
+ {
+ if(_ufilename != "") {
+ _fileEntry->setPath(_ufilename);
+ } else if(_filename != "") {
+ _fileEntry->setPath(_filename);
+ } else {
+ _fileEntry->setPath("index.html");
+ }
+ }
+public:
+ SingleFileDownloadContext(int32_t pieceLength,
+ int64_t totalLength,
+ const string& filename,
+ const string& ufilename = ""):
+ _pieceLength(pieceLength),
+ _fileEntry(new FileEntry(filename, totalLength, 0)),
+ _filename(filename),
+ _ufilename(ufilename)
+ {
+ updateFileEntry();
+ }
+
+ virtual ~SingleFileDownloadContext() {}
+
+ virtual string getPieceHash(int32_t index) const
+ {
+ if(index < 0 || _pieceHashes.size() <= (size_t)index) {
+ return "";
+ }
+ return _pieceHashes[index];
+ }
+
+ virtual const Strings& getPieceHashes() const
+ {
+ return _pieceHashes;
+ }
+
+ virtual int64_t getTotalLength() const
+ {
+ return _fileEntry->getLength();
+ }
+
+ virtual FILE_MODE getFileMode() const
+ {
+ return SINGLE;
+ }
+
+ virtual FileEntries getFileEntries() const
+ {
+ FileEntries fs;
+ fs.push_back(_fileEntry);
+ return fs;
+ }
+
+ virtual string getName() const
+ {
+ return _filename;
+ }
+
+ virtual int32_t getPieceLength() const
+ {
+ return _pieceLength;
+ }
+
+ virtual int32_t getNumPieces() const
+ {
+ return (_fileEntry->getLength()+_pieceLength-1)/_pieceLength;
+ }
+
+ virtual string getActualBasePath() const
+ {
+ return _dir+"/"+_fileEntry->getPath();
+ }
+
+ virtual string getPieceHashAlgo() const
+ {
+ return _pieceHashAlgo;
+ }
+
+ void setPieceHashes(const Strings& pieceHashes)
+ {
+ _pieceHashes = pieceHashes;
+ }
+
+ void setFilename(const string& filename)
+ {
+ _filename = filename;
+ updateFileEntry();
+ }
+
+ void setUFilename(const string& ufilename)
+ {
+ _ufilename = ufilename;
+ updateFileEntry();
+ }
+
+ void setTotalLength(int64_t totalLength)
+ {
+ _fileEntry->setLength(totalLength);
+ }
+
+ void setPieceHashAlgo(const string& algo)
+ {
+ _pieceHashAlgo = algo;
+ }
+};
+
+typedef SharedHandle<SingleFileDownloadContext> SingleFileDownloadContextHandle;
+
+#endif // _D_SINGLE_FILE_DOWNLOAD_CONTEXT_H_
diff --git a/src/SocketCore.cc b/src/SocketCore.cc
index 66466a9e..45b61667 100644
--- a/src/SocketCore.cc
+++ b/src/SocketCore.cc
@@ -33,8 +33,6 @@
*/
/* copyright --> */
#include "SocketCore.h"
-#include "DlRetryEx.h"
-#include "DlAbortEx.h"
#include "message.h"
#include "a2netcompat.h"
#include "a2time.h"
@@ -56,7 +54,8 @@ SocketCore::SocketCore(int32_t sockfd):sockfd(sockfd) {
init();
}
-void SocketCore::init() {
+void SocketCore::init()
+{
use = 1;
blocking = true;
secure = false;
@@ -81,7 +80,9 @@ SocketCore::~SocketCore() {
#endif // HAVE_LIBGNUTLS
}
-void SocketCore::beginListen(int32_t port) {
+void SocketCore::beginListen(int32_t port)
+ throw(DlAbortEx*)
+{
closeConnection();
//sockfd = socket(AF_UNSPEC, SOCK_STREAM, PF_UNSPEC);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
@@ -116,7 +117,9 @@ void SocketCore::beginListen(int32_t port) {
setNonBlockingMode();
}
-SocketCore* SocketCore::acceptConnection() const {
+SocketCore* SocketCore::acceptConnection() const
+ throw(DlAbortEx*)
+{
struct sockaddr_in sockaddr;
socklen_t len = sizeof(sockaddr);
memset((char*)&sockaddr, 0, sizeof(sockaddr));
@@ -129,7 +132,9 @@ SocketCore* SocketCore::acceptConnection() const {
return s;
}
-void SocketCore::getAddrInfo(pair<string, int32_t>& addrinfo) const {
+void SocketCore::getAddrInfo(pair<string, int32_t>& addrinfo) const
+ throw(DlAbortEx*)
+{
struct sockaddr_in listenaddr;
memset((char*)&listenaddr, 0, sizeof(listenaddr));
socklen_t len = sizeof(listenaddr);
@@ -140,7 +145,9 @@ void SocketCore::getAddrInfo(pair<string, int32_t>& addrinfo) const {
addrinfo.second = ntohs(listenaddr.sin_port);
}
-void SocketCore::getPeerInfo(pair<string, int32_t>& peerinfo) const {
+void SocketCore::getPeerInfo(pair<string, int32_t>& peerinfo) const
+ throw(DlAbortEx*)
+{
struct sockaddr_in peerin;
memset(&peerin, 0, sizeof(peerin));
int32_t len = sizeof(peerin);
@@ -151,7 +158,9 @@ void SocketCore::getPeerInfo(pair<string, int32_t>& peerinfo) const {
peerinfo.second = ntohs(peerin.sin_port);
}
-void SocketCore::establishConnection(const string& host, int32_t port) {
+void SocketCore::establishConnection(const string& host, int32_t port)
+ throw(DlAbortEx*)
+{
closeConnection();
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1) {
@@ -199,7 +208,9 @@ WSAEWOULDBLOCK
}
}
-void SocketCore::setNonBlockingMode() {
+void SocketCore::setNonBlockingMode()
+ throw(DlAbortEx*)
+{
#ifdef __MINGW32__
static u_long flag = 1;
if (::ioctlsocket(sockfd, FIONBIO, &flag) == -1) {
@@ -213,7 +224,9 @@ void SocketCore::setNonBlockingMode() {
blocking = false;
}
-void SocketCore::setBlockingMode() {
+void SocketCore::setBlockingMode()
+ throw(DlAbortEx*)
+{
#ifdef __MINGW32__
static u_long flag = 0;
if (::ioctlsocket(sockfd, FIONBIO, &flag) == -1) {
@@ -227,7 +240,8 @@ void SocketCore::setBlockingMode() {
blocking = true;
}
-void SocketCore::closeConnection() {
+void SocketCore::closeConnection()
+{
#ifdef HAVE_LIBSSL
// for SSL
if(secure) {
@@ -262,7 +276,9 @@ void SocketCore::closeConnection() {
#endif // HAVE_LIBGNUTLS
}
-bool SocketCore::isWritable(int32_t timeout) const {
+bool SocketCore::isWritable(int32_t timeout) const
+ throw(DlRetryEx*)
+{
fd_set fds;
FD_ZERO(&fds);
FD_SET(sockfd, &fds);
@@ -286,7 +302,9 @@ bool SocketCore::isWritable(int32_t timeout) const {
}
}
-bool SocketCore::isReadable(int32_t timeout) const {
+bool SocketCore::isReadable(int32_t timeout) const
+ throw(DlRetryEx*)
+{
#ifdef HAVE_LIBGNUTLS
if(secure && peekBufLength > 0) {
return true;
@@ -315,7 +333,9 @@ bool SocketCore::isReadable(int32_t timeout) const {
}
}
-void SocketCore::writeData(const char* data, int32_t len) {
+void SocketCore::writeData(const char* data, int32_t len)
+ throw(DlRetryEx*)
+{
int32_t ret = 0;
if(!secure) {
@@ -338,7 +358,9 @@ void SocketCore::writeData(const char* data, int32_t len) {
}
}
-void SocketCore::readData(char* data, int32_t& len) {
+void SocketCore::readData(char* data, int32_t& len)
+ throw(DlRetryEx*)
+{
int32_t ret = 0;
if(!secure) {
@@ -363,7 +385,9 @@ void SocketCore::readData(char* data, int32_t& len) {
len = ret;
}
-void SocketCore::peekData(char* data, int32_t& len) {
+void SocketCore::peekData(char* data, int32_t& len)
+ throw(DlRetryEx*)
+{
int32_t ret = 0;
if(!secure) {
@@ -389,7 +413,8 @@ void SocketCore::peekData(char* data, int32_t& len) {
}
#ifdef HAVE_LIBGNUTLS
-int32_t SocketCore::shiftPeekData(char* data, int32_t len) {
+int32_t SocketCore::shiftPeekData(char* data, int32_t len)
+{
if(peekBufLength <= len) {
memcpy(data, peekBuf, peekBufLength);
int32_t ret = peekBufLength;
@@ -407,7 +432,8 @@ int32_t SocketCore::shiftPeekData(char* data, int32_t len) {
}
-void SocketCore::addPeekData(char* data, int32_t len) {
+void SocketCore::addPeekData(char* data, int32_t len)
+{
if(peekBufLength+len > peekBufMax) {
char* temp = new char[peekBufMax+len];
memcpy(temp, peekBuf, peekBufLength);
@@ -419,7 +445,9 @@ void SocketCore::addPeekData(char* data, int32_t len) {
peekBufLength += len;
}
-int32_t SocketCore::gnutlsRecv(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) {
int32_t ret = gnutls_record_recv(sslSession, data+plen, len-plen);
@@ -432,7 +460,9 @@ int32_t SocketCore::gnutlsRecv(char* data, int32_t len) {
}
}
-int32_t SocketCore::gnutlsPeek(char* data, int32_t len) {
+int32_t SocketCore::gnutlsPeek(char* data, int32_t len)
+ throw(DlRetryEx*)
+{
if(peekBufLength >= len) {
memcpy(data, peekBuf, len);
return len;
@@ -448,7 +478,9 @@ int32_t SocketCore::gnutlsPeek(char* data, int32_t len) {
}
#endif // HAVE_LIBGNUTLS
-void SocketCore::initiateSecureConnection() {
+void SocketCore::initiateSecureConnection()
+ throw(DlAbortEx*)
+{
#ifdef HAVE_LIBSSL
// for SSL
if(!secure) {
@@ -518,15 +550,18 @@ void SocketCore::initiateSecureConnection() {
secure = true;
}
-/* static */ int SocketCore::error() {
+/* static */ int SocketCore::error()
+{
return SOCKET_ERRNO;
}
-/* static */ const char *SocketCore::errorMsg() {
+/* static */ const char *SocketCore::errorMsg()
+{
return errorMsg(SOCKET_ERRNO);
}
-/* static */ const char *SocketCore::errorMsg(const int err) {
+/* static */ const char *SocketCore::errorMsg(const int err)
+{
#ifndef __MINGW32__
return strerror(err);
#else
diff --git a/src/SocketCore.h b/src/SocketCore.h
index 6c35b1ef..8a5b44c6 100644
--- a/src/SocketCore.h
+++ b/src/SocketCore.h
@@ -36,6 +36,8 @@
#define _D_SOCKET_CORE_H_
#include "common.h"
+#include "DlRetryEx.h"
+#include "DlAbortEx.h"
#include <string>
#include <utility>
@@ -75,8 +77,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);
- int32_t gnutlsPeek(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*);
#endif // HAVE_LIBGNUTLS
void init();
@@ -97,26 +99,26 @@ public:
* @param port port to listen. If 0 is specified, os automaticaly
* choose avaiable port.
*/
- void beginListen(int32_t port = 0);
+ void beginListen(int32_t port = 0) throw(DlAbortEx*);
/**
* 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;
+ void getAddrInfo(pair<string, int32_t>& addrinfo) const throw(DlAbortEx*);
/**
* 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;
+ void getPeerInfo(pair<string, int32_t>& peerinfo) const throw(DlAbortEx*);
/**
* 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;
+ SocketCore* acceptConnection() const throw(DlAbortEx*);
/**
* Connects to the server named host and the destination port is port.
@@ -126,14 +128,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);
+ void establishConnection(const string& host, int32_t port) throw(DlAbortEx*);
- void setNonBlockingMode();
+ void setNonBlockingMode() throw(DlAbortEx*);
/**
* Makes this socket blocking mode.
*/
- void setBlockingMode();
+ void setBlockingMode() throw(DlAbortEx*);
/**
* Closes the connection of this socket.
@@ -147,7 +149,7 @@ public:
* @return true if the socket is available for writing,
* otherwise returns false.
*/
- bool isWritable(int32_t timeout) const;
+ bool isWritable(int32_t timeout) const throw(DlRetryEx*);
/**
* Checks whether this socket is available for reading.
@@ -156,7 +158,7 @@ public:
* @return true if the socket is available for reading,
* otherwise returns false.
*/
- bool isReadable(int32_t timeout) const;
+ bool isReadable(int32_t timeout) const throw(DlRetryEx*);
/**
* Writes characters into this socket. data is a pointer pointing the first
@@ -166,8 +168,11 @@ public:
* @param data data to write
* @param len length of data
*/
- void writeData(const char* data, int32_t len);
- void writeData(const string& msg) { writeData(msg.c_str(), msg.size()); }
+ void writeData(const char* data, int32_t len) throw(DlRetryEx*);
+ void writeData(const string& msg) throw(DlRetryEx*)
+ {
+ writeData(msg.c_str(), msg.size());
+ }
/**
* Reads up to len bytes from this socket.
@@ -181,7 +186,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);
+ void readData(char* data, int32_t& len) throw(DlRetryEx*);
/**
* Reads up to len bytes from this socket, but bytes are not removed from
@@ -192,14 +197,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);
+ void peekData(char* data, int32_t& len) throw(DlRetryEx*);
/**
* 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() ;
+ void initiateSecureConnection() throw(DlAbortEx*);
bool operator==(const SocketCore& s) {
return sockfd == s.sockfd;
diff --git a/src/FileAllocator.h b/src/StatCalc.h
index 43e68b84..ba3ce80d 100644
--- a/src/FileAllocator.h
+++ b/src/StatCalc.h
@@ -32,29 +32,27 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
-#ifndef _D_FILE_ALLOCATOR_H_
-#define _D_FILE_ALLOCATOR_H_
+#ifndef _D_STAT_CALC_H_
+#define _D_STAT_CALC_H_
#include "common.h"
-#include "FileAllocationMonitor.h"
-#include "NullFileAllocationMonitor.h"
-class FileAllocator {
-protected:
- FileAllocationMonitorHandle fileAllocationMonitor;
-public:
- FileAllocator():fileAllocationMonitor(new NullFileAllocationMonitor()) {}
-
- virtual ~FileAllocator() {}
+class RequestGroupMan;
+extern typedef SharedHandle<RequestGroupMan> RequestGroupManHandle;
+class FileAllocationMan;
+extern typedef SharedHandle<FileAllocationMan> FileAllocationManHandle;
+class CheckIntegrityMan;
+extern typedef SharedHandle<CheckIntegrityMan> CheckIntegrityManHandle;
- virtual void allocate(int fd, int64_t totalLength) = 0;
+class StatCalc {
+public:
+ virtual ~StatCalc() {}
- void setFileAllocationMonitor(const FileAllocationMonitorHandle& monitor)
- {
- this->fileAllocationMonitor = monitor;
- }
+ virtual void calculateStat(const RequestGroupManHandle& requestGroupMan,
+ const FileAllocationManHandle& fileAllocationMan,
+ const CheckIntegrityManHandle& checkIntegrityMan) = 0;
};
-typedef SharedHandle<FileAllocator> FileAllocatorHandle;
+typedef SharedHandle<StatCalc> StatCalcHandle;
-#endif // _D_FILE_ALLOCATOR_H_
+#endif // _D_STAT_CALC_H_
diff --git a/src/TorrentDownloadEngine.h b/src/StreamCheckIntegrityEntry.cc
index ba0cfda1..f2e607ce 100644
--- a/src/TorrentDownloadEngine.h
+++ b/src/StreamCheckIntegrityEntry.cc
@@ -32,60 +32,44 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
-#ifndef _D_TORRENT_DOWNLOAD_ENGINE_H_
-#define _D_TORRENT_DOWNLOAD_ENGINE_H_
-
+#include "StreamCheckIntegrityEntry.h"
+#include "RequestGroup.h"
#include "DownloadEngine.h"
-#include "TimeA2.h"
-#include "BtContext.h"
-#include "BtRuntime.h"
+#include "StreamFileAllocationEntry.h"
+#include "InitiateConnectionCommandFactory.h"
+#include "CUIDCounter.h"
#include "PieceStorage.h"
-#include "PeerStorage.h"
-#include "BtAnnounce.h"
-#include "BtProgressInfoFile.h"
-
-class TorrentDownloadEngine : public DownloadEngine {
-private:
- bool filenameFixed;
-
- void initStatistics();
- void calculateStatistics();
-protected:
- Time cp;
- Time lastCalcStat;
- int32_t downloadSpeed;
- int32_t uploadSpeed;
- int64_t selectedDownloadLengthDiff;
- int64_t selectedTotalLength;
- // The time when startup
- Time startup;
- // The average speed(bytes per second) since startup
- int32_t avgSpeed;
- // The estimated remaining time to complete the download.
- int32_t eta;
- int64_t downloadLength;
- int64_t uploadLength;
- int64_t totalLength;
-
- BtContextHandle btContext;
- BtRuntimeHandle btRuntime;
- PieceStorageHandle pieceStorage;
- PeerStorageHandle peerStorage;
- BtAnnounceHandle btAnnounce;
- BtProgressInfoFileHandle btProgressInfoFile;
-
- int32_t calculateSpeed(int64_t sessionLength, int32_t elapsed);
- void calculateStat();
-
- virtual void onEndOfRun();
- virtual void sendStatistics() = 0;
-public:
- TorrentDownloadEngine();
- virtual ~TorrentDownloadEngine();
+#include "FileAllocationMan.h"
+#include "DiskAdaptor.h"
- bool isFilenameFixed() const { return filenameFixed; }
+StreamCheckIntegrityEntry::StreamCheckIntegrityEntry(const RequestHandle& currentRequest,
+ RequestGroup* requestGroup,
+ Command* nextCommand):
+ CheckIntegrityEntry(requestGroup, nextCommand),
+ _currentRequest(currentRequest)
+{}
- void setBtContext(const BtContextHandle& btContext);
-};
+StreamCheckIntegrityEntry::~StreamCheckIntegrityEntry() {}
-#endif // _D_TORRENT_DOWNLOAD_ENGINE_H_
+Commands StreamCheckIntegrityEntry::prepareForNextAction(DownloadEngine* e)
+{
+ Commands commands;
+ if(_requestGroup->isFileAllocationEnabled() && !_requestGroup->getPieceStorage()->getDiskAdaptor()->fileAllocationIterator()->finished()) {
+ 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));
+ }
+ }
+ return commands;
+}
diff --git a/src/StreamCheckIntegrityEntry.h b/src/StreamCheckIntegrityEntry.h
new file mode 100644
index 00000000..7b864962
--- /dev/null
+++ b/src/StreamCheckIntegrityEntry.h
@@ -0,0 +1,65 @@
+/* <!-- 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_STREAM_CHECK_INTEGRITY_ENTRY_H_
+#define _D_STREAM_CHECK_INTEGRITY_ENTRY_H_
+
+#include "CheckIntegrityEntry.h"
+#include "TimeA2.h"
+
+class Request;
+typedef SharedHandle<Request> RequestHandle;
+class Command;
+typedef deque<Command*> Commands;
+class RequestGroup;
+class DownloadEngine;
+
+class StreamCheckIntegrityEntry:public CheckIntegrityEntry
+{
+private:
+ RequestHandle _currentRequest;
+ Time _timer;
+public:
+ StreamCheckIntegrityEntry(const RequestHandle& currentRequest,
+ RequestGroup* requestGroup,
+ Command* nextCommand = 0);
+
+ virtual ~StreamCheckIntegrityEntry();
+
+ virtual Commands prepareForNextAction(DownloadEngine* e);
+};
+
+typedef SharedHandle<StreamCheckIntegrityEntry> StreamCheckIntegrityEntryHandle;
+
+#endif // _D_STREAM_CHECK_INTEGRITY_ENTRY_H_
diff --git a/src/DefaultFileAllocator.cc b/src/StreamFileAllocationEntry.cc
index 5ab85f3d..b229a0a2 100644
--- a/src/DefaultFileAllocator.cc
+++ b/src/StreamFileAllocationEntry.cc
@@ -32,39 +32,38 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
-#include "DefaultFileAllocator.h"
-#include "DlAbortEx.h"
-#include "TimeA2.h"
-#include "a2io.h"
-#include <sys/types.h>
-#include <unistd.h>
-#include <errno.h>
+#include "StreamFileAllocationEntry.h"
+#include "CUIDCounter.h"
+#include "Command.h"
+#include "DownloadEngine.h"
+#include "Option.h"
+#include "Request.h"
+#include "prefs.h"
+#include "RequestGroup.h"
+#include "InitiateConnectionCommandFactory.h"
-void DefaultFileAllocator::allocate(int fd, int64_t totalLength)
+StreamFileAllocationEntry::StreamFileAllocationEntry(const RequestHandle& currentRequest,
+ RequestGroup* requestGroup,
+ Command* nextCommand):
+ FileAllocationEntry(requestGroup, nextCommand),
+ _currentRequest(currentRequest)
+{}
+
+StreamFileAllocationEntry::~StreamFileAllocationEntry() {}
+
+Commands StreamFileAllocationEntry::prepareForNextAction(DownloadEngine* e)
{
- if(0 != lseek(fd, 0, SEEK_SET)) {
- throw new DlAbortEx("Seek failed: %s", strerror(errno));
- }
- int32_t bufSize = 4096;
- char buf[4096];
- memset(buf, 0, bufSize);
- int64_t x = (totalLength+bufSize-1)/bufSize;
- fileAllocationMonitor->setMinValue(0);
- fileAllocationMonitor->setMaxValue(totalLength);
- fileAllocationMonitor->setCurrentValue(0);
- fileAllocationMonitor->showProgress();
- Time cp;
- for(int64_t i = 0; i < x; ++i) {
- if(write(fd, buf, bufSize) < 0) {
- throw new DlAbortEx("Allocation failed: %s", strerror(errno));
- }
- if(cp.elapsedInMillis(500)) {
- fileAllocationMonitor->setCurrentValue(i*bufSize);
- fileAllocationMonitor->showProgress();
- cp.reset();
- }
+ Commands commands;
+ if(_timer.difference() <= e->option->getAsInt(PREF_DIRECT_DOWNLOAD_TIMEOUT) &&
+ _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));
}
- fileAllocationMonitor->setCurrentValue(totalLength);
- fileAllocationMonitor->showProgress();
- ftruncate(fd, totalLength);
+ return commands;
}
diff --git a/src/TrackerUpdateCommand.h b/src/StreamFileAllocationEntry.h
index 3c50fe9d..df272883 100644
--- a/src/TrackerUpdateCommand.h
+++ b/src/StreamFileAllocationEntry.h
@@ -32,27 +32,30 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
-#ifndef _D_TRACKER_UPDATE_COMMAND_H_
-#define _D_TRACKER_UPDATE_COMMAND_H_
+#ifndef _D_STREAM_FILE_ALLOCATION_ENTRY_H_
+#define _D_STREAM_FILE_ALLOCATION_ENTRY_H_
-#include "BtContextAwareCommand.h"
-#include "TorrentDownloadEngine.h"
-#include "Logger.h"
+#include "FileAllocationEntry.h"
+#include "TimeA2.h"
-class TrackerUpdateCommand : public BtContextAwareCommand {
+class Request;
+extern typedef SharedHandle<Request> RequestHandle;
+
+class StreamFileAllocationEntry : public FileAllocationEntry {
private:
- TorrentDownloadEngine* e;
- const Logger* logger;
- bool prepareForRetry();
- string getTrackerResponse();
+ RequestHandle _currentRequest;
+ Time _timer;
public:
- TrackerUpdateCommand(int32_t cuid,
- TorrentDownloadEngine* e,
- const BtContextHandle& btContext);
+ StreamFileAllocationEntry(const RequestHandle& currentRequest,
+ RequestGroup* requestGroup,
+ Command* nextCommand = 0);
- virtual ~TrackerUpdateCommand();
+ virtual ~StreamFileAllocationEntry();
- bool execute();
+ virtual Commands prepareForNextAction(DownloadEngine* e);
};
-#endif // _D_TRACKER_UPDATE_COMMAND_H_
+typedef SharedHandle<StreamFileAllocationEntry> StreamFileAllocationEntryHandle;
+typedef deque<StreamFileAllocationEntryHandle> StreamFileAllocationEntries;
+
+#endif // _D_STREAM_FILE_ALLOCATION_ENTRY_H_
diff --git a/src/TimeBasedCommand.cc b/src/TimeBasedCommand.cc
index 1803a38e..ac26bb2d 100644
--- a/src/TimeBasedCommand.cc
+++ b/src/TimeBasedCommand.cc
@@ -33,6 +33,12 @@
*/
/* copyright --> */
#include "TimeBasedCommand.h"
+#include "DownloadEngine.h"
+
+TimeBasedCommand::TimeBasedCommand(int32_t cuid, DownloadEngine* e, int32_t interval):
+ Command(cuid), _e(e),_exit(false), _interval(interval) {}
+
+TimeBasedCommand::~TimeBasedCommand() {}
bool TimeBasedCommand::execute()
{
diff --git a/src/TimeBasedCommand.h b/src/TimeBasedCommand.h
index f23353f6..b4829e5c 100644
--- a/src/TimeBasedCommand.h
+++ b/src/TimeBasedCommand.h
@@ -37,7 +37,8 @@
#include "Command.h"
#include "TimeA2.h"
-#include "DownloadEngine.h"
+
+class DownloadEngine;
class TimeBasedCommand : public Command
{
@@ -73,10 +74,9 @@ public:
virtual void postProcess() {};
public:
- TimeBasedCommand(int32_t cuid, DownloadEngine* e, int32_t interval):
- Command(cuid), _e(e),_exit(false), _interval(interval) {}
+ TimeBasedCommand(int32_t cuid, DownloadEngine* e, int32_t interval);
- virtual ~TimeBasedCommand() {}
+ virtual ~TimeBasedCommand();
virtual bool execute();
};
diff --git a/src/TorrentDownloadEngine.cc b/src/TorrentDownloadEngine.cc
deleted file mode 100644
index 1a5f4017..00000000
--- a/src/TorrentDownloadEngine.cc
+++ /dev/null
@@ -1,116 +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 "TorrentDownloadEngine.h"
-#include "Util.h"
-#include "BtRegistry.h"
-
-TorrentDownloadEngine::TorrentDownloadEngine():
- filenameFixed(false),
- btContext(0),
- btRuntime(0),
- pieceStorage(0),
- peerStorage(0),
- btAnnounce(0),
- btProgressInfoFile(0) {}
-
-TorrentDownloadEngine::~TorrentDownloadEngine() {
-}
-
-void TorrentDownloadEngine::setBtContext(const BtContextHandle& btContext) {
- this->btContext = btContext;
- btRuntime = BT_RUNTIME(btContext);
- pieceStorage = PIECE_STORAGE(btContext);
- peerStorage = PEER_STORAGE(btContext);
- btAnnounce = BT_ANNOUNCE(btContext);
- btProgressInfoFile = BT_PROGRESS_INFO_FILE(btContext);
-}
-
-void TorrentDownloadEngine::onEndOfRun() {
- pieceStorage->getDiskAdaptor()->closeFile();
- if(pieceStorage->allDownloadFinished()) {
- btProgressInfoFile->removeFile();
- } else {
- btProgressInfoFile->save();
- }
-}
-
-void TorrentDownloadEngine::initStatistics() {
- downloadSpeed = 0;
- uploadSpeed = 0;
- cp.reset();
- startup.reset();
- eta = 0;
- avgSpeed = 0;
- downloadLength = 0;
- uploadLength = 0;
- totalLength = 0;
-}
-
-int32_t TorrentDownloadEngine::calculateSpeed(int64_t length, int32_t elapsed) {
- int32_t nowSpeed = length/elapsed;
- return nowSpeed;
-}
-
-void TorrentDownloadEngine::calculateStat() {
- TransferStat stat = peerStorage->calculateStat();
-
- if(pieceStorage->isSelectiveDownloadingMode()) {
- downloadLength = pieceStorage->getFilteredCompletedLength();
- totalLength = pieceStorage->getFilteredTotalLength();
- } else {
- downloadLength = pieceStorage->getCompletedLength();
- totalLength = pieceStorage->getTotalLength();
- }
- uploadLength = stat.getSessionUploadLength()+
- btRuntime->getUploadLengthAtStartup();
-
- downloadSpeed = stat.getDownloadSpeed();
- uploadSpeed = stat.getUploadSpeed();
- avgSpeed = calculateSpeed(stat.getSessionDownloadLength(),
- startup.difference());
- if(avgSpeed < 0) {
- avgSpeed = 0;
- } else if(avgSpeed != 0) {
- eta = (totalLength-downloadLength)/avgSpeed;
- }
-}
-
-void TorrentDownloadEngine::calculateStatistics() {
- if(cp.difference() >= 1) {
- calculateStat();
- sendStatistics();
- cp.reset();
- }
-}
diff --git a/src/TorrentRequestInfo.cc b/src/TorrentRequestInfo.cc
deleted file mode 100644
index 1eb6391b..00000000
--- a/src/TorrentRequestInfo.cc
+++ /dev/null
@@ -1,130 +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 "TorrentRequestInfo.h"
-#include "DownloadEngineFactory.h"
-#include "prefs.h"
-#include "Util.h"
-#include "BtRegistry.h"
-#include "DefaultBtContext.h"
-#include "FatalException.h"
-#include "message.h"
-#include "RecoverableException.h"
-#include "DNSCache.h"
-#include <signal.h>
-
-#ifndef SA_RESETHAND
-# define SA_RESETHAND 0x80000000
-#endif // SA_RESETHAND
-
-extern volatile sig_atomic_t btHaltRequested;
-
-void torrentHandler(int signal) {
- btHaltRequested = 1;
-}
-
-RequestInfos TorrentRequestInfo::execute() {
- {
- DNSCacheHandle dnsCache = new NullDNSCache();
- DNSCacheSingletonHolder::instance(dnsCache);
- }
-
- DefaultBtContextHandle btContext = new DefaultBtContext();
- btContext->load(torrentFile);
- if(op->defined(PREF_PEER_ID_PREFIX)) {
- btContext->setPeerIdPrefix(op->get(PREF_PEER_ID_PREFIX));
- }
-
- if(op->get(PREF_SHOW_FILES) == V_TRUE) {
- Util::toStream(cout, btContext->getFileEntries());
- return RequestInfos();
- }
- // set max_tries to 1. AnnounceList handles retries.
- op->put(PREF_MAX_TRIES, "1");
- SharedHandle<TorrentDownloadEngine>
- e(DownloadEngineFactory::newTorrentConsoleEngine(btContext,
- op,
- targetFiles));
-
- if(BT_PROGRESS_INFO_FILE(btContext)->exists()) {
- // load .aria2 file if it exists.
- BT_PROGRESS_INFO_FILE(btContext)->load();
- PIECE_STORAGE(btContext)->getDiskAdaptor()->openFile();
-#ifdef ENABLE_MESSAGE_DIGEST
- if(op->get(PREF_CHECK_INTEGRITY) == V_TRUE) {
- PIECE_STORAGE(btContext)->checkIntegrity();
- }
-#endif // ENABLE_MESSAGE_DIGEST
- } else {
- if(PIECE_STORAGE(btContext)->getDiskAdaptor()->fileExists()) {
- if(op->get(PREF_ALLOW_OVERWRITE) != V_TRUE) {
- logger->notice(MSG_FILE_ALREADY_EXISTS,
- PIECE_STORAGE(btContext)->getDiskAdaptor()->getFilePath().c_str(),
- BT_PROGRESS_INFO_FILE(btContext)->getFilename().c_str());
- throw new FatalException(EX_DOWNLOAD_ABORTED);
- } else {
- PIECE_STORAGE(btContext)->getDiskAdaptor()->openFile();
-#ifdef ENABLE_MESSAGE_DIGEST
- if(op->get(PREF_CHECK_INTEGRITY) == V_TRUE) {
- PIECE_STORAGE(btContext)->markAllPiecesDone();
- PIECE_STORAGE(btContext)->checkIntegrity();
- }
-#endif // ENABLE_MESSAGE_DIGEST
- }
- } else {
- PIECE_STORAGE(btContext)->getDiskAdaptor()->openFile();
- }
- }
-
- Util::setGlobalSignalHandler(SIGINT, torrentHandler, SA_RESETHAND);
- Util::setGlobalSignalHandler(SIGTERM, torrentHandler, SA_RESETHAND);
-
- try {
- e->run();
- if(PIECE_STORAGE(btContext)->downloadFinished()) {
- printDownloadCompeleteMessage();
- }
- } catch(RecoverableException* ex) {
- logger->error(EX_EXCEPTION_CAUGHT, ex);
- fail = true;
- delete ex;
- }
- // TODO we want just 1 torrent download to clear
- BtRegistry::clear();
-
- Util::setGlobalSignalHandler(SIGINT, SIG_DFL, 0);
- Util::setGlobalSignalHandler(SIGTERM, SIG_DFL, 0);
-
- return RequestInfos();
-}
diff --git a/src/TrackerUpdateCommand.cc b/src/TrackerUpdateCommand.cc
deleted file mode 100644
index b66cda17..00000000
--- a/src/TrackerUpdateCommand.cc
+++ /dev/null
@@ -1,115 +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 "TrackerUpdateCommand.h"
-#include "LogFactory.h"
-#include "DlAbortEx.h"
-#include "message.h"
-#include "PeerInitiateConnectionCommand.h"
-#include "SleepCommand.h"
-#include "Util.h"
-#include "CUIDCounter.h"
-#include <sstream>
-
-TrackerUpdateCommand::TrackerUpdateCommand(int32_t cuid,
- TorrentDownloadEngine* e,
- const BtContextHandle& btContext):
- BtContextAwareCommand(cuid, btContext), e(e)
-{
- logger = LogFactory::getInstance();
-}
-
-TrackerUpdateCommand::~TrackerUpdateCommand() {}
-
-bool TrackerUpdateCommand::prepareForRetry() {
- e->commands.push_back(this);
- return false;
-}
-
-string TrackerUpdateCommand::getTrackerResponse() {
- stringstream strm;
- char data[2048];
- try {
- while(1) {
- int32_t dataLength = e->_requestGroupMan->getRequestGroup(0)->getSegmentMan()->diskWriter->readData(data, sizeof(data), strm.tellp());
- strm.write(data, dataLength);
- if(dataLength != sizeof(data)) {
- break;
- }
- }
- return strm.str();
- } catch(RecoverableException* e) {
- throw;
- }
-}
-
-bool TrackerUpdateCommand::execute() {
- if(btAnnounce->noMoreAnnounce()) {
- return true;
- }
- if(e->_requestGroupMan->countRequestGroup() == 0 ||
- !e->_requestGroupMan->downloadFinished()) {
- return prepareForRetry();
- }
-
- try {
- string trackerResponse = getTrackerResponse();
-
- btAnnounce->processAnnounceResponse(trackerResponse.c_str(),
- trackerResponse.size());
- while(!btRuntime->isHalt() && btRuntime->lessThanMinPeer()) {
- PeerHandle peer = peerStorage->getUnusedPeer();
- if(peer.isNull()) {
- break;
- }
- peer->cuid = CUIDCounterSingletonHolder::instance()->newID();
- PeerInitiateConnectionCommand* command =
- new PeerInitiateConnectionCommand(peer->cuid,
- peer,
- e,
- btContext);
- e->commands.push_back(command);
- logger->debug("CUID#%d - Adding new command CUID#%d", cuid, peer->cuid);
- }
- btAnnounce->announceSuccess();
- btAnnounce->resetAnnounce();
- e->_requestGroupMan->removeStoppedGroup();
- } catch(RecoverableException* err) {
- logger->error(MSG_TRACKER_RESPONSE_PROCESSING_FAILED, err, cuid);
- e->_requestGroupMan->getRequestGroup(0)->getSegmentMan()->errors++;
- delete err;
- }
- return prepareForRetry();
-}
-
diff --git a/src/TrackerWatcherCommand.cc b/src/TrackerWatcherCommand.cc
index 49ebc899..600c727b 100644
--- a/src/TrackerWatcherCommand.cc
+++ b/src/TrackerWatcherCommand.cc
@@ -33,18 +33,28 @@
*/
/* copyright --> */
#include "TrackerWatcherCommand.h"
-#include "InitiateConnectionCommandFactory.h"
+#include "DownloadEngine.h"
#include "Util.h"
-#include "SleepCommand.h"
#include "prefs.h"
-#include "RequestFactory.h"
-#include "TrackerSegmentManFactory.h"
#include "message.h"
+#include "SingleFileDownloadContext.h"
+#include "ByteArrayDiskWriterFactory.h"
+#include "RecoverableException.h"
+#include "CUIDCounter.h"
+#include "PeerInitiateConnectionCommand.h"
+#include "DiskAdaptor.h"
+#include "RequestGroup.h"
+#include "Option.h"
-TrackerWatcherCommand::TrackerWatcherCommand(int cuid,
- TorrentDownloadEngine* e,
+TrackerWatcherCommand::TrackerWatcherCommand(int32_t cuid,
+ RequestGroup* requestGroup,
+ DownloadEngine* e,
const BtContextHandle& btContext):
- BtContextAwareCommand(cuid, btContext), e(e)
+ Command(cuid),
+ BtContextAwareCommand(btContext),
+ RequestGroupAware(requestGroup),
+ e(e),
+ _trackerRequestGroup(0)
{
}
@@ -53,53 +63,107 @@ TrackerWatcherCommand::~TrackerWatcherCommand() {}
bool TrackerWatcherCommand::execute() {
if(btAnnounce->noMoreAnnounce()) {
+ logger->debug("no more announce");
return true;
}
- Command* command = createCommand();
- if(command) {
- e->commands.push_back(command);
+ if(_trackerRequestGroup.isNull()) {
+ _trackerRequestGroup = createAnnounce();
+ if(!_trackerRequestGroup.isNull()) {
+ //e->_requestGroupMan->addReservedGroup(_trackerRequestGroup);
+ //e->_requestGroupMan->fillRequestGroupFromReserver(e);
+ e->addCommand(_trackerRequestGroup->createInitialCommand(e));
+ logger->debug("added tracker request command");
+ }
+ } else if(_trackerRequestGroup->downloadFinished()){
+ try {
+ string trackerResponse = getTrackerResponse(_trackerRequestGroup);
+
+ processTrackerResponse(trackerResponse);
+ btAnnounce->announceSuccess();
+ btAnnounce->resetAnnounce();
+ } catch(DlAbortEx* ex) {
+ btAnnounce->announceFailure();
+ if(btAnnounce->isAllAnnounceFailed()) {
+ btAnnounce->resetAnnounce();
+ }
+ delete ex;
+ }
+ _trackerRequestGroup = 0;
+ } else if(_trackerRequestGroup->getNumCommand() == 0){
+ // handle errors here
+ btAnnounce->announceFailure(); // inside it, trackers = 0.
+ _trackerRequestGroup = 0;
+ if(btAnnounce->isAllAnnounceFailed()) {
+ btAnnounce->resetAnnounce();
+ }
}
e->commands.push_back(this);
return false;
}
-Command* TrackerWatcherCommand::createCommand() {
- Command* command = 0;
+string TrackerWatcherCommand::getTrackerResponse(const RequestGroupHandle& requestGroup)
+{
+ stringstream strm;
+ char data[2048];
+ requestGroup->getPieceStorage()->getDiskAdaptor()->openFile();
+ while(1) {
+ int32_t dataLength = requestGroup->getPieceStorage()->getDiskAdaptor()->readData((unsigned char*)data, sizeof(data), strm.tellp());
+ strm.write(data, dataLength);
+ if(dataLength == 0) {
+ break;
+ }
+ }
+ return strm.str();
+}
+
+// TODO we have to deal with the exception thrown By BtAnnounce
+void TrackerWatcherCommand::processTrackerResponse(const string& trackerResponse)
+{
+ btAnnounce->processAnnounceResponse(trackerResponse.c_str(),
+ trackerResponse.size());
+ while(!btRuntime->isHalt() && btRuntime->lessThanMinPeer()) {
+ PeerHandle peer = peerStorage->getUnusedPeer();
+ if(peer.isNull()) {
+ break;
+ }
+ peer->cuid = CUIDCounterSingletonHolder::instance()->newID();
+ PeerInitiateConnectionCommand* command =
+ new PeerInitiateConnectionCommand(peer->cuid,
+ _requestGroup,
+ peer,
+ e,
+ btContext);
+ e->commands.push_back(command);
+ logger->debug("CUID#%d - Adding new command CUID#%d", cuid, peer->cuid);
+ }
+}
+RequestGroupHandle TrackerWatcherCommand::createAnnounce() {
+ RequestGroupHandle rg = 0;
if(btAnnounce->isAnnounceReady()) {
- command = createRequestCommand(btAnnounce->getAnnounceUrl());
+ rg = createRequestGroup(btAnnounce->getAnnounceUrl());
btAnnounce->announceStart(); // inside it, trackers++.
- } else if(e->_requestGroupMan->getErrors() > 0) {
- btAnnounce->announceFailure(); // inside it, trackers = 0.
- e->_requestGroupMan->removeStoppedGroup();
- if(btAnnounce->isAllAnnounceFailed()) {
- btAnnounce->resetAnnounce();
- return 0;
- } else if(btAnnounce->isAnnounceReady()) {
- command =
- new SleepCommand(cuid, e,
- createRequestCommand(btAnnounce->getAnnounceUrl()),
- e->option->getAsInt(PREF_RETRY_WAIT));
- btAnnounce->announceStart(); // inside it, tracker++.
- }
}
- return command;
+ return rg;
}
-Command* TrackerWatcherCommand::createRequestCommand(const string& url)
+RequestGroupHandle
+TrackerWatcherCommand::createRequestGroup(const string& uri)
{
- RequestGroupHandle rg = new RequestGroup(url, e->option);
- rg->setUserDefinedFilename("[tracker.announce]");
- rg->isTorrent = true;
- rg->setSegmentManFactory(new TrackerSegmentManFactory(e->option));
- e->_requestGroupMan->addRequestGroup(rg);
- Commands commands = e->_requestGroupMan->getInitialCommands(e);
+ Strings uris;
+ uris.push_back(uri);
+ RequestGroupHandle rg = new RequestGroup(e->option, uris);
- if(commands.empty()) {
- logger->error(MSG_TRACKER_REQUEST_CREATION_FAILED, cuid);
- return 0;
- }
- logger->info(MSG_CREATING_TRACKER_REQUEST, cuid,
- commands.front()->getCuid());
- return commands.front();
+ SingleFileDownloadContextHandle dctx =
+ new SingleFileDownloadContext(e->option->getAsInt(PREF_SEGMENT_SIZE),
+ 0,
+ "",
+ "[tracker.announce]");
+ dctx->setDir("");
+ rg->setDownloadContext(dctx);
+ rg->setDiskWriterFactory(new ByteArrayDiskWriterFactory());
+ rg->setFileAllocationEnabled(false);
+ rg->setPreLocalFileCheckEnabled(false);
+ logger->info("Creating tracker request group GID#%d", rg->getGID());
+ return rg;
}
diff --git a/src/TrackerWatcherCommand.h b/src/TrackerWatcherCommand.h
index 785fa7c3..4cc02f93 100644
--- a/src/TrackerWatcherCommand.h
+++ b/src/TrackerWatcherCommand.h
@@ -35,28 +35,43 @@
#ifndef _D_TRACKER_WATCHER_COMMAND_H_
#define _D_TRACKER_WATCHER_COMMAND_H_
+#include "Command.h"
#include "BtContextAwareCommand.h"
-#include "TorrentDownloadEngine.h"
+#include "RequestGroupAware.h"
-class TrackerWatcherCommand : public BtContextAwareCommand {
+class DownloadEngine;
+class RequestGroup;
+extern typedef SharedHandle<RequestGroup> RequestGroupHandle;
+
+class TrackerWatcherCommand : public Command,
+ public BtContextAwareCommand,
+ public RequestGroupAware
+{
private:
- TorrentDownloadEngine* e;
+ DownloadEngine* e;
+ RequestGroupHandle _trackerRequestGroup;
/**
* Returns a command for announce request. Returns 0 if no announce request
* is needed.
*/
- Command* createRequestCommand(const string& url);
+ RequestGroupHandle createRequestGroup(const string& url);
+
+ string getTrackerResponse(const RequestGroupHandle& requestGroup);
+
+ void processTrackerResponse(const string& response);
+
public:
- TrackerWatcherCommand(int cuid,
- TorrentDownloadEngine* e,
+ TrackerWatcherCommand(int32_t cuid,
+ RequestGroup* requestGroup,
+ DownloadEngine* e,
const BtContextHandle& btContext);
- ~TrackerWatcherCommand();
+ virtual ~TrackerWatcherCommand();
- Command* createCommand();
+ RequestGroupHandle createAnnounce();
- bool execute();
+ virtual bool execute();
};
#endif // _D_TRACKER_WATCHER_COMMAND_H_
diff --git a/src/TransferStat.cc b/src/TransferStat.cc
new file mode 100644
index 00000000..95cef7b9
--- /dev/null
+++ b/src/TransferStat.cc
@@ -0,0 +1,45 @@
+/* <!-- 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 "TransferStat.h"
+
+TransferStat operator+(const TransferStat& a, const TransferStat& b)
+{
+ TransferStat c;
+ c.downloadSpeed = a.downloadSpeed+b.downloadSpeed;
+ c.uploadSpeed = a.uploadSpeed+b.uploadSpeed;
+ c.sessionUploadLength = a.sessionUploadLength+b.sessionUploadLength;
+ c.sessionDownloadLength = a.sessionDownloadLength+b.sessionDownloadLength;
+ return c;
+}
diff --git a/src/TransferStat.h b/src/TransferStat.h
new file mode 100644
index 00000000..ac782d74
--- /dev/null
+++ b/src/TransferStat.h
@@ -0,0 +1,121 @@
+/* <!-- 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_TRANSFER_STAT_H_
+#define _D_TRANSFER_STAT_H_
+
+#include "common.h"
+
+class TransferStat {
+public:
+ int32_t downloadSpeed;
+ int32_t uploadSpeed;
+ int64_t sessionDownloadLength;
+ int64_t sessionUploadLength;
+ int64_t allTimeUploadLength;
+
+ void copy(const TransferStat& stat)
+ {
+ downloadSpeed = stat.downloadSpeed;
+ uploadSpeed = stat.uploadSpeed;
+ sessionDownloadLength = stat.sessionDownloadLength;
+ sessionUploadLength = stat.sessionUploadLength;
+ allTimeUploadLength = stat.allTimeUploadLength;
+ }
+public:
+ TransferStat():downloadSpeed(0), uploadSpeed(0),
+ sessionDownloadLength(0), sessionUploadLength(0),
+ allTimeUploadLength(0) {}
+
+ TransferStat(const TransferStat& stat)
+ {
+ copy(stat);
+ }
+
+ TransferStat& operator=(const TransferStat& stat)
+ {
+ if(this != &stat) {
+ copy(stat);
+ }
+ return *this;
+ }
+
+ friend TransferStat operator+(const TransferStat& a, const TransferStat& b);
+
+ int32_t getDownloadSpeed() const {
+ return downloadSpeed;
+ }
+
+ void setDownloadSpeed(int32_t s) { downloadSpeed = s; }
+
+ int32_t getUploadSpeed() const {
+ return uploadSpeed;
+ }
+
+ void setUploadSpeed(int32_t s) { uploadSpeed = s; }
+
+ /**
+ * Returns the number of bytes downloaded since the program started.
+ * This is not the total number of bytes downloaded.
+ */
+ int64_t getSessionDownloadLength() const {
+ return sessionDownloadLength;
+ }
+
+ void setSessionDownloadLength(int64_t s) { sessionDownloadLength = s; }
+
+ /**
+ * Returns the number of bytes uploaded since the program started.
+ * This is not the total number of bytes uploaded.
+ */
+ int64_t getSessionUploadLength() const {
+ return sessionUploadLength;
+ }
+
+ void setSessionUploadLength(int64_t s) { sessionUploadLength = s; }
+
+ void setAllTimeUploadLength(int64_t s)
+ {
+ allTimeUploadLength = s;
+ }
+
+ int64_t getAllTimeUploadLength() const
+ {
+ return allTimeUploadLength;
+ }
+};
+
+TransferStat operator+(const TransferStat& a, const TransferStat& b);
+
+#endif // _D_TRANSFER_STAT_H_
diff --git a/src/UnknownLengthPieceStorage.cc b/src/UnknownLengthPieceStorage.cc
new file mode 100644
index 00000000..3955c889
--- /dev/null
+++ b/src/UnknownLengthPieceStorage.cc
@@ -0,0 +1,171 @@
+/* <!-- 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 "UnknownLengthPieceStorage.h"
+#include "DefaultDiskWriter.h"
+#include "DirectDiskAdaptor.h"
+#include "prefs.h"
+#include "DefaultDiskWriterFactory.h"
+#include "DownloadContext.h"
+#include "PieceStorage.h"
+#include "Piece.h"
+
+UnknownLengthPieceStorage::UnknownLengthPieceStorage(const DownloadContextHandle& downloadContext,
+ const Option* option):
+ _downloadContext(downloadContext),
+ _option(option),
+ _diskAdaptor(0),
+ _diskWriterFactory(new DefaultDiskWriterFactory()),
+ _totalLength(0),
+ _downloadFinished(false),
+ _piece(0) {}
+
+UnknownLengthPieceStorage::~UnknownLengthPieceStorage() {}
+
+void UnknownLengthPieceStorage::initStorage()
+{
+ DiskWriterHandle writer = _diskWriterFactory->newDiskWriter();
+ DirectDiskAdaptorHandle directDiskAdaptor = new DirectDiskAdaptor();
+ directDiskAdaptor->setDiskWriter(writer);
+ directDiskAdaptor->setTotalLength(_downloadContext->getTotalLength());
+ _diskAdaptor = directDiskAdaptor;
+ string storeDir = _downloadContext->getDir();
+// if(storeDir == "") {
+// storeDir = ".";
+// }
+ _diskAdaptor->setStoreDir(storeDir);
+ _diskAdaptor->setFileEntries(_downloadContext->getFileEntries());
+}
+
+PieceHandle UnknownLengthPieceStorage::getMissingPiece()
+{
+ if(_downloadFinished) {
+ return 0;
+ }
+ if(_piece.isNull()) {
+ _piece = new Piece();
+ return _piece;
+ } else {
+ return 0;
+ }
+}
+
+PieceHandle UnknownLengthPieceStorage::getMissingPiece(int32_t index)
+{
+ if(index == 0) {
+ return getMissingPiece();
+ } else {
+ return 0;
+ }
+}
+
+PieceHandle UnknownLengthPieceStorage::getPiece(int32_t index)
+{
+ if(index == 0) {
+ if(_piece.isNull()) {
+ return new Piece();
+ } else {
+ return _piece;
+ }
+ } else {
+ return 0;
+ }
+}
+
+void UnknownLengthPieceStorage::completePiece(const PieceHandle& piece)
+{
+ if(_piece == piece) {
+ _downloadFinished = true;
+ _totalLength = _piece->getLength();
+ _piece = 0;
+ }
+}
+
+void UnknownLengthPieceStorage::cancelPiece(const PieceHandle& piece)
+{
+ if(_piece == piece) {
+ _piece = 0;
+ }
+}
+
+bool UnknownLengthPieceStorage::hasPiece(int32_t index)
+{
+ if(index == 0 && _downloadFinished) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool UnknownLengthPieceStorage::isPieceUsed(int32_t index)
+{
+ if(index == 0 && !_piece.isNull()) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+DiskAdaptorHandle UnknownLengthPieceStorage::getDiskAdaptor()
+{
+ return _diskAdaptor;
+}
+
+int32_t UnknownLengthPieceStorage::getPieceLength(int32_t index)
+{
+ if(index == 0) {
+ return _totalLength;
+ } else {
+ return 0;
+ }
+}
+
+void UnknownLengthPieceStorage::markAllPiecesDone()
+{
+ if(!_piece.isNull()) {
+ _totalLength = _piece->getLength();
+ _piece = 0;
+ }
+ _downloadFinished = true;
+}
+
+Pieces UnknownLengthPieceStorage::getInFlightPieces()
+{
+ return Pieces();
+}
+
+void UnknownLengthPieceStorage::setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory)
+{
+ _diskWriterFactory = diskWriterFactory;
+}
diff --git a/src/UnknownLengthPieceStorage.h b/src/UnknownLengthPieceStorage.h
new file mode 100644
index 00000000..8b4ee353
--- /dev/null
+++ b/src/UnknownLengthPieceStorage.h
@@ -0,0 +1,272 @@
+/* <!-- 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_UNKNOWN_LENGTH_PIECE_STORAGE_H_
+#define _D_UNKNOWN_LENGTH_PIECE_STORAGE_H_
+
+#include "PieceStorage.h"
+
+class Option;
+class DownloadContext;
+extern typedef SharedHandle<DownloadContext> DownloadContextHandle;
+class DiskWriterFactory;
+extern typedef SharedHandle<DiskWriterFactory> DiskWriterFactoryHandle;
+
+class UnknownLengthPieceStorage:public PieceStorage {
+private:
+ DownloadContextHandle _downloadContext;
+
+ const Option* _option;
+
+ DiskAdaptorHandle _diskAdaptor;
+
+ DiskWriterFactoryHandle _diskWriterFactory;
+
+ int64_t _totalLength;
+
+ bool _downloadFinished;
+
+ PieceHandle _piece;
+public:
+ UnknownLengthPieceStorage(const DownloadContextHandle& downloadContext,
+ const Option* option);
+
+ virtual ~UnknownLengthPieceStorage();
+
+ /**
+ * Returns true if the peer has a piece that localhost doesn't have.
+ * Otherwise returns false.
+ */
+ virtual bool hasMissingPiece(const PeerHandle& peer)
+ {
+ abort();
+ }
+
+ /**
+ * Returns a piece that the peer has but localhost doesn't.
+ * The piece will be marked "used" status in order to prevent other command
+ * from get the same piece. But in end game mode, same piece may be returned
+ * to several commands.
+ */
+ virtual PieceHandle getMissingPiece(const PeerHandle& peer)
+ {
+ abort();
+ }
+ /**
+ * Returns a piece that the peer has but localhost doesn't.
+ * Only pieces that declared as "fast" are returned.
+ * The piece will be marked "used" status in order to prevent other command
+ * from get the same piece. But in end game mode, same piece may be returned
+ * to several commands.
+ */
+ virtual PieceHandle getMissingFastPiece(const PeerHandle& peer)
+ {
+ abort();
+ }
+ /**
+ * Returns a missing piece if available. Otherwise returns 0;
+ */
+ virtual PieceHandle getMissingPiece();
+
+ /**
+ * Returns a missing piece whose index is index.
+ * If a piece whose index is index is already acquired or currently used,
+ * then returns 0.
+ * Also returns 0 if any of missing piece is not available.
+ */
+ virtual PieceHandle getMissingPiece(int32_t index);
+
+ /**
+ * Returns the piece denoted by index.
+ * No status of the piece is changed in this method.
+ */
+ virtual PieceHandle getPiece(int32_t index);
+
+ /**
+ * Tells that the download of the specfied piece completes.
+ */
+ virtual void completePiece(const PieceHandle& piece);
+
+ /**
+ * Tells that the download of the specified piece is canceled.
+ */
+ virtual void cancelPiece(const PieceHandle& piece);
+
+ /**
+ * Returns true if the specified piece is already downloaded.
+ * Otherwise returns false.
+ */
+ virtual bool hasPiece(int32_t index);
+
+ virtual bool isPieceUsed(int32_t index);
+
+ virtual int64_t getTotalLength()
+ {
+ return _totalLength;
+ }
+
+ virtual int64_t getFilteredTotalLength()
+ {
+ return _totalLength;
+ }
+
+ virtual int64_t getCompletedLength()
+ {
+ // TODO we have to return actual completed length here?
+ return _totalLength;
+ }
+
+ virtual int64_t getFilteredCompletedLength()
+ {
+ return getCompletedLength();
+ }
+
+ virtual void setFileFilter(const Strings& filePaths) {}
+
+ virtual void setFileFilter(const Integers& fileIndexes) {}
+
+ virtual void clearFileFilter() {}
+
+ /**
+ * Returns true if download has completed.
+ * If file filter is enabled, then returns true if those files have
+ * downloaded.
+ */
+ virtual bool downloadFinished()
+ {
+ return _downloadFinished;
+ }
+
+ /**
+ * Returns true if all files have downloaded.
+ * The file filter is ignored.
+ */
+ virtual bool allDownloadFinished()
+ {
+ return downloadFinished();
+ }
+
+ /**
+ * Initializes DiskAdaptor.
+ * TODO add better documentation here.
+ */
+ virtual void initStorage();
+
+ virtual const unsigned char* getBitfield()
+ {
+ return 0;
+ }
+
+ virtual void setBitfield(const unsigned char* bitfield,
+ int32_t bitfieldLength) {}
+
+ virtual int32_t getBitfieldLength()
+ {
+ return 0;
+ }
+
+ virtual bool isSelectiveDownloadingMode()
+ {
+ return false;
+ }
+
+ virtual void finishSelectiveDownloadingMode() {}
+
+ virtual bool isEndGame()
+ {
+ return false;
+ }
+
+ virtual DiskAdaptorHandle getDiskAdaptor();
+
+ virtual int32_t getPieceLength(int32_t index);
+
+ /**
+ * Adds piece index to advertise to other commands. They send have message
+ * based on this information.
+ */
+ virtual void advertisePiece(int32_t cuid, int32_t index) {}
+
+ /**
+ * Returns piece index which is not advertised by the caller command and
+ * newer than lastCheckTime.
+ */
+ virtual Integers getAdvertisedPieceIndexes(int32_t myCuid,
+ const Time& lastCheckTime)
+ {
+ return Integers();
+ }
+
+ /**
+ * Removes have entry if specified seconds have elapsed since its
+ * registration.
+ */
+ virtual void removeAdvertisedPiece(int32_t elapsed) {}
+
+ /**
+ * Sets all bits in bitfield to 1.
+ */
+ virtual void markAllPiecesDone();
+
+ virtual void markPiecesDone(int64_t length)
+ {
+ // TODO not implemented yet
+ abort();
+ }
+
+ virtual void markPieceMissing(int32_t index)
+ {
+ // TODO not implemented yet
+ abort();
+ }
+
+ /**
+ * Do nothing because loading in-flight piece is not supported for this
+ * class.
+ */
+ virtual void addInFlightPiece(const Pieces& pieces) {}
+
+ virtual int32_t countInFlightPiece()
+ {
+ return 0;
+ }
+
+ virtual Pieces getInFlightPieces();
+
+ void setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory);
+};
+
+typedef SharedHandle<UnknownLengthPieceStorage> UnknownLengthPieceStorageHandle;
+
+#endif // _D_UNKNOWN_LENGTH_PIECE_STORAGE_H_
diff --git a/src/Util.cc b/src/Util.cc
index bbd31465..3afe870e 100644
--- a/src/Util.cc
+++ b/src/Util.cc
@@ -33,7 +33,6 @@
*/
/* copyright --> */
#include "Util.h"
-#include "DlAbortEx.h"
#include "File.h"
#include "message.h"
#include "SimpleRandomizer.h"
@@ -54,7 +53,8 @@
#endif // HAVE_SLEEP
template<typename T>
-string uint2str(T value, bool comma) {
+string uint2str(T value, bool comma)
+{
string str;
if(value == 0) {
str = "0";
@@ -74,7 +74,8 @@ string uint2str(T value, bool comma) {
}
template<typename T>
-string int2str(T value, bool comma) {
+string int2str(T value, bool comma)
+{
bool flag = false;
if(value < 0) {
flag = true;
@@ -89,23 +90,28 @@ string int2str(T value, bool comma) {
-string Util::uitos(uint16_t value, bool comma) {
+string Util::uitos(uint16_t value, bool comma)
+{
return uint2str<uint16_t>(value, comma);
}
-string Util::itos(int16_t value, bool comma) {
+string Util::itos(int16_t value, bool comma)
+{
return int2str<int16_t>(value, comma);
}
-string Util::uitos(uint32_t value, bool comma) {
+string Util::uitos(uint32_t value, bool comma)
+{
return uint2str<uint32_t>(value, comma);
}
-string Util::itos(int32_t value, bool comma) {
+string Util::itos(int32_t value, bool comma)
+{
return int2str<int32_t>(value, comma);
}
-string Util::ullitos(uint64_t value, bool comma) {
+string Util::ullitos(uint64_t value, bool comma)
+{
return uint2str<uint64_t>(value, comma);
}
@@ -114,7 +120,8 @@ string Util::llitos(int64_t value, bool comma)
return int2str<int64_t>(value, comma);
}
-string Util::trim(const string& src, const string& trimCharset) {
+string Util::trim(const string& src, const string& trimCharset)
+{
string::size_type sp = src.find_first_not_of(trimCharset);
string::size_type ep = src.find_last_not_of(trimCharset);
if(sp == string::npos || ep == string::npos) {
@@ -124,7 +131,8 @@ string Util::trim(const string& src, const string& trimCharset) {
}
}
-void Util::split(pair<string, string>& hp, const string& src, char delim) {
+void Util::split(pair<string, string>& hp, const string& src, char delim)
+{
hp.first = "";
hp.second = "";
string::size_type p = src.find(delim);
@@ -322,7 +330,9 @@ void Util::fileCopy(const string& dest, const string& src) {
rangedFileCopy(dest, src, 0, file.size());
}
-void Util::rangedFileCopy(const string& dest, const string& src, int64_t srcOffset, int64_t length) {
+void Util::rangedFileCopy(const string& dest, const string& src, int64_t srcOffset, int64_t length)
+ throw(DlAbortEx*)
+{
int32_t bufSize = 4096;
char buf[bufSize];
int32_t destFd = -1;
diff --git a/src/Util.h b/src/Util.h
index 66163f2d..7f85d699 100644
--- a/src/Util.h
+++ b/src/Util.h
@@ -36,6 +36,7 @@
#define _D_UTIL_H_
#include "common.h"
+#include "DlAbortEx.h"
#include "a2time.h"
#include "FileEntry.h"
#include <utility>
@@ -93,7 +94,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);
+ static void rangedFileCopy(const string& destFile, const string& src, int64_t srcOffset, int64_t length) throw(DlAbortEx*);
static bool isPowerOf(int32_t num, int32_t base);
diff --git a/src/main.cc b/src/main.cc
index 837360e1..b7e171b4 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -37,14 +37,10 @@
#include "Util.h"
#include "FeatureConfig.h"
#include "MultiUrlRequestInfo.h"
-#include "TorrentRequestInfo.h"
#include "BitfieldManFactory.h"
#include "SimpleRandomizer.h"
-#include "ConsoleFileAllocationMonitor.h"
#include "Netrc.h"
#include "RequestFactory.h"
-#include "OptionParser.h"
-#include "OptionHandlerFactory.h"
#include "FatalException.h"
#include "File.h"
#include "CUIDCounter.h"
@@ -59,6 +55,9 @@
#include "prefs.h"
#include "ParameterizedStringParser.h"
#include "PStringBuildVisitor.h"
+#include "SingleFileDownloadContext.h"
+#include "DefaultBtContext.h"
+#include "RequestGroup.h"
#include <deque>
#include <algorithm>
#include <signal.h>
@@ -66,14 +65,13 @@
#include <libgen.h>
#include <utility>
#include <fstream>
-#include <sstream>
extern char* optarg;
extern int optind, opterr, optopt;
#include <getopt.h>
#ifdef ENABLE_METALINK
-#include "MetalinkRequestInfo.h"
#include "Xml2MetalinkProcessor.h"
+#include "Metalink2RequestGroup.h"
#endif
#ifdef HAVE_LIBSSL
@@ -85,282 +83,6 @@ extern int optind, opterr, optopt;
# include <gnutls/gnutls.h>
#endif // HAVE_LIBGNUTLS
-using namespace std;
-
-void showVersion() {
- cout << PACKAGE << _(" version ") << PACKAGE_VERSION << endl;
- cout << "**Configuration**" << endl;
- cout << FeatureConfig::getInstance()->getConfigurationSummary();
-#ifdef ENABLE_MESSAGE_DIGEST
- cout << "message digest algorithms: " << MessageDigestContext::getSupportedAlgoString() << endl;
-#endif // ENABLE_MESSAGE_DIGEST
- cout << endl;
- cout << "Copyright (C) 2006, 2007 Tatsuhiro Tsujikawa" << endl;
- cout << endl;
- cout <<
- _("This program is free software; you can redistribute it and/or modify\n"
- "it under the terms of the GNU General Public License as published by\n"
- "the Free Software Foundation; either version 2 of the License, or\n"
- "(at your option) any later version.\n"
- "\n"
- "This program is distributed in the hope that it will be useful,\n"
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
- "GNU General Public License for more details.\n"
- "\n"
- "You should have received a copy of the GNU General Public License\n"
- "along with this program; if not, write to the Free Software\n"
- "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n");
- cout << endl;
- cout << _("Contact Info:") << endl;
- cout << "Tatsuhiro Tsujikawa <tujikawa at users dot sourceforge dot net>" << endl;
- cout << endl;
-
-}
-
-void showUsage() {
- printf(_("Usage: %s [options] URL ...\n"), PACKAGE_NAME);
-#ifdef ENABLE_BITTORRENT
- printf(_(" %s [options] -T TORRENT_FILE FILE ...\n"), PACKAGE_NAME);
-#endif // ENABLE_BITTORRENT
-#ifdef ENABLE_METALINK
- printf(_(" %s [options] -M METALINK_FILE\n"), PACKAGE_NAME);
-#endif // ENABLE_METALINK
- cout << endl;
- cout << _("Options:") << endl;
- cout << _(" -d, --dir=DIR The directory to store the downloaded file.") << endl;
- cout << _(" -o, --out=FILE The file name of the downloaded file.") << endl;
- cout << _(" -l, --log=LOG The file name of the log file. If '-' is\n"
- " specified, log is written to stdout.") << endl;
-#ifdef HAVE_DAEMON
- cout << _(" -D, --daemon Run as daemon.") << endl;
-#endif // HAVE_DAEMON
- cout << _(" -s, --split=N Download a file using N connections. N must be\n"
- " between 1 and 5. This option affects all URLs.\n"
- " Thus, aria2 connects to each URL with\n"
- " N connections.\n"
- " Default: 1") << endl;
- cout << _(" --retry-wait=SEC Set the seconds to wait to retry after an error\n"
- " has occured. Specify a value between 0 and 60.\n"
- " Default: 5") << endl;
- cout << _(" -t, --timeout=SEC Set timeout in seconds. Default: 60") << endl;
- cout << _(" -m, --max-tries=N Set number of tries. 0 means unlimited.\n"
- " Default: 5") << endl;
- /*
- cout << _(" --min-segment-size=SIZE[K|M] Set minimum segment size. You can append\n"
- " K or M(1K = 1024, 1M = 1024K). This\n"
- " value must be greater than or equal to\n"
- " 1024. Default: 1M") << endl;
- */
- cout << _(" --http-proxy=HOST:PORT Use HTTP proxy server. This affects all URLs.") << endl;
- cout << _(" --http-user=USER Set HTTP user. This affects all URLs.") << endl;
- cout << _(" --http-passwd=PASSWD Set HTTP password. This affects all URLs.") << endl;
- cout << _(" --http-proxy-user=USER Set HTTP proxy user. This affects all URLs.") << endl;
- cout << _(" --http-proxy-passwd=PASSWD Set HTTP proxy password. This affects all URLs.") << endl;
- cout << _(" --http-proxy-method=METHOD Set the method to use in proxy request.\n"
- " METHOD is either 'get' or 'tunnel'.\n"
- " Default: tunnel") << endl;
- cout << _(" --http-auth-scheme=SCHEME Set HTTP authentication scheme. Currently, basic\n"
- " is the only supported scheme.\n"
- " Default: basic") << endl;
- cout << _(" --referer=REFERER Set Referer. This affects all URLs.") << endl;
- cout << _(" --ftp-user=USER Set FTP user. This affects all URLs.\n"
- " Default: anonymous") << endl;
- cout << _(" --ftp-passwd=PASSWD Set FTP password. This affects all URLs.\n"
- " Default: ARIA2USER@") << endl;
- cout << _(" --ftp-type=TYPE Set FTP transfer type. TYPE is either 'binary'\n"
- " or 'ascii'.\n"
- " Default: binary") << endl;
- cout << _(" -p, --ftp-pasv Use passive mode in FTP.") << endl;
- cout << _(" --ftp-via-http-proxy=METHOD Use HTTP proxy in FTP. METHOD is either 'get' or\n"
- " 'tunnel'.\n"
- " Default: tunnel") << endl;
- cout << _(" --lowest-speed-limit=SPEED Close connection if download speed is lower than\n"
- " or equal to this value(bytes per sec).\n"
- " 0 means aria2 does not have a lowest speed limit.\n"
- " You can append K or M(1K = 1024, 1M = 1024K).\n"
-
- " This option does not affect BitTorrent downloads.\n"
- " Default: 0") << endl;
- cout << _(" --max-download-limit=SPEED Set max download speed in bytes per sec.\n"
- " 0 means unrestricted.\n"
- " You can append K or M(1K = 1024, 1M = 1024K).\n"
- " Default: 0") << endl;
- cout << _(" --file-allocation=METHOD Specify file allocation method. METHOD is either\n"
- " 'none' or 'prealloc'. 'none' doesn't pre-allocate\n"
- " file space. 'prealloc' pre-allocates file space\n"
- " before download begins. This may take some time\n"
- " depending on the size of the file.\n"
- " Default: none") << endl;
- cout << _(" --allow-overwrite=true|false If false, aria2 doesn't download a file which\n"
- " already exists but the corresponding .aria2 file\n"
- " doesn't exist.\n"
- " Default: false") << endl;
- cout << _(" -Z, --force-sequential[=true|false] Fetch URIs in the command-line sequentially\n"
- " and download each URI in a separate session, like\n"
- " the usual command-line download utilities.\n"
- " Default: false") << endl;
- cout << _(" --auto-file-renaming[=true|false] Rename file name if the same file already\n"
- " exists. This option works only in http(s)/ftp\n"
- " download.\n"
- " The new file name has a dot and a number(1..9999)\n"
- " appended.\n"
- " Default: true") << endl;
- cout << _(" -P, --parameterized-uri[=true|false] Enable parameterized URI support.\n"
- " You can specify set of parts:\n"
- " http://{sv1,sv2,sv3}/foo.iso\n"
- " Also you can specify numeric sequences with step\n"
- " counter:\n"
- " http://host/image[000-100:2].img\n"
- " A step counter can be omitted.\n"
- " If all URIs do not point to the same file, such\n"
- " as the second example above, -Z option is\n"
- " required.\n"
- " Default: false") << endl;
-#ifdef ENABLE_MESSAGE_DIGEST
- cout << _(" --check-integrity=true|false Check file integrity by validating piece hash.\n"
- " This option only affects in BitTorrent downloads\n"
- " and Metalink downloads with chunk checksums.\n"
- " Use this option to re-download a damaged portion\n"
- " of a file.\n"
- " You may need to specify --allow-overwrite=true\n"
- " if the .aria2 file doesn't exist.\n"
- " Default: false") << endl;
- cout << _(" --realtime-chunk-checksum=true|false Validate chunk checksum while\n"
- " downloading a file in Metalink mode. This option\n"
- " on affects Metalink mode with chunk checksums.\n"
- " Default: true") << endl;
-#endif // ENABLE_MESSAGE_DIGEST
- cout << _(" -c, --continue Continue downloading a partially downloaded\n"
- " file. Use this option to resume a download\n"
- " started by a web browser or another program\n"
- " which downloads files sequentially from the\n"
- " beginning. Currently this option is only\n"
- " applicable to http(s)/ftp downloads.") << endl;
- cout << _(" -U, --user-agent=USER_AGENT Set user agent for http(s) downloads.") << endl;
- cout << _(" -n, --no-netrc Disables netrc support.") << endl;
- cout << _(" -i, --input-file=FILE Downloads URIs found in FILE. You can specify\n"
- " multiple URIs for a single entity: separate\n"
- " URIs on a single line using the TAB character.\n"
- " Reads input from stdin when '-' is specified.") << endl;
- cout << _(" -j, --max-concurrent-downloads=N Set maximum number of concurrent downloads.\n"
- " It should be used with the -i option.\n"
- " Default: 5") << endl;
- cout << _(" --load-cookies=FILE Load cookies from FILE. The format of FILE is\n"
- " the same used by Netscape and Mozilla.") << endl;
-#if defined ENABLE_BITTORRENT || ENABLE_METALINK
- cout << _(" -S, --show-files Print file listing of .torrent or .metalink file\n"
- " and exit.") << endl;
- cout << _(" --select-file=INDEX... Set file to download by specifing its index.\n"
- " You can find the file index using the\n"
- " --show-files option. Multiple indexes can be\n"
- " specified by using ',', for example: \"3,6\".\n"
- " You can also use '-' to specify a range: \"1-5\".\n"
- " ',' and '-' can be used together.\n"
- " When used with the -M option, index may vary\n"
- " depending on the query(see --metalink-* options).") << endl;
-#endif // ENABLE_BITTORRENT || ENABLE_METALINK
-#ifdef ENABLE_BITTORRENT
- cout << _(" -T, --torrent-file=TORRENT_FILE The path to the .torrent file.") << endl;
- cout << _(" --follow-torrent=true|false Set to false to prevent aria2 from\n"
- " entering BitTorrent mode even if the filename of\n"
- " the downloaded file ends with .torrent.\n"
- " Default: true") << endl;
- cout << _(" --direct-file-mapping=true|false Directly read from and write to each file\n"
- " mentioned in .torrent file.\n"
- " Default: true") << endl;
- cout << _(" --listen-port=PORT Set TCP port number for BitTorrent downloads.\n"
- " Default: 6881-6999") << endl;
- cout << _(" --max-upload-limit=SPEED Set max upload speed in bytes per sec.\n"
- " 0 means unrestricted.\n"
- " You can append K or M(1K = 1024, 1M = 1024K).\n"
- " Default: 0") << endl;
- cout << _(" --seed-time=MINUTES Specify seeding time in minutes. Also see the\n"
- " --seed-ratio option.") << endl;
- cout << _(" --seed-ratio=RATIO Specify share ratio. Seed completed torrents\n"
- " until share ratio reaches RATIO. 1.0 is\n"
- " encouraged. If --seed-time option is specified\n"
- " along with this option, seeding ends when at\n"
- " least one of the conditions is satisfied.") << endl;
- cout << _(" --peer-id-prefix=PEERI_ID_PREFIX Specify the prefix of peer ID. The peer ID in\n"
- " in BitTorrent is 20 byte length. If more than 20\n"
- " bytes are specified, only first 20\n"
- " bytes are used. If less than 20 bytes are\n"
- " specified, the random alphabet characters are\n"
- " added to make it's length 20 bytes.\n"
- " Default: -aria2-") << endl;
-#endif // ENABLE_BITTORRENT
-#ifdef ENABLE_METALINK
- cout << _(" -M, --metalink-file=METALINK_FILE The file path to the .metalink file.") << endl;
- cout << _(" -C, --metalink-servers=NUM_SERVERS The number of servers to connect to\n"
- " simultaneously.\n"
- " Default: 5") << endl;
- cout << _(" --metalink-version=VERSION The version of the file to download.") << endl;
- cout << _(" --metalink-language=LANGUAGE The language of the file to download.") << endl;
- cout << _(" --metalink-os=OS The operating system of the file to download.") << endl;
- cout << _(" --metalink-location=LOCATION The location of the prefered server.") << endl;
- cout << _(" --follow-metalink=true|false Set to false to prevent aria2 from\n"
- " entering Metalink mode even if the filename of\n"
- " the downloaded file ends with .metalink.\n"
- " Default: true") << endl;
-#endif // ENABLE_METALINK
- cout << _(" -v, --version Print the version number and exit.") << endl;
- cout << _(" -h, --help Print this message and exit.") << endl;
- cout << endl;
- cout << "URL:" << endl;
- cout << _(" You can specify multiple URLs. All URLs must point to the same file\n"
- " or downloading will fail.") << endl;
- cout << endl;
-#ifdef ENABLE_BITTORRENT
- cout << "FILE:" << endl;
- cout << _(" Specify files in multi-file torrent to download. Use in conjunction with the\n"
- " -T option. This argument is ignored if you specify the --select-file option.") << endl;
- cout << endl;
-#endif // ENABLE_BITTORRENT
- cout << _("Examples:") << endl;
- cout << _(" Download a file using 1 connection:") << endl;
- cout << " aria2c http://AAA.BBB.CCC/file.zip" << endl;
- cout << _(" Download a file using 2 connections:") << endl;
- cout << " aria2c -s 2 http://AAA.BBB.CCC/file.zip" << endl;
- cout << _(" Download a file using 2 connections, each connects to a different server:") << endl;
- cout << " aria2c http://AAA.BBB.CCC/file.zip http://DDD.EEE.FFF/GGG/file.zip" << endl;
- cout << _(" You can mix up different protocols:") << endl;
- cout << " aria2c http://AAA.BBB.CCC/file.zip ftp://DDD.EEE.FFF/GGG/file.zip" << endl;
- cout << _(" Parameterized URI:") << endl;
- cout << " aria2c -P http://{server1,server2,server3}/file.iso" << endl;
- cout << _(" Parameterized URI. -Z option is required in this case:") << endl;
- cout << " aria2c -P -Z http://host/file[001-100:2].img" << endl;
-#ifdef ENABLE_BITTORRENT
- cout << endl;
- cout << _(" Download a torrent:") << endl;
- cout << " aria2c -o test.torrent http://AAA.BBB.CCC/file.torrent" << endl;
- cout << _(" Download a torrent using a local .torrent file:") << endl;
- cout << " aria2c -T test.torrent" << endl;
- cout << _(" Download only selected files:") << endl;
- cout << " aria2c -T test.torrent dir/file1.zip dir/file2.zip" << endl;
- cout << _(" Print file listing of .torrent file:") << endl;
- cout << " aria2c -T test.torrent -S" << endl;
-#endif // ENABLE_BITTORRENT
-#ifdef ENABLE_METALINK
- cout << endl;
- cout << _(" Metalink downloading:") << endl;
- cout << " aria2c http://AAA.BBB.CCC/file.metalink" << endl;
- cout << _(" Download a file using local .metalink file:") << endl;
- cout << " aria2c -M test.metalink" << endl;
- cout << _(" Metalink downloading with preferences:") << endl;
- cout << " aria2c -M test.metalink --metalink-version=1.1.1 --metalink-language=en-US" << endl;
- cout << _(" Download only selected files:") << endl;
- cout << " aria2c -M test.metalink --metalink-language=en-US dir/file1.zip dir/file2.zip" << endl;
- cout << _(" Download only selected files using index:") << endl;
- cout << " aria2c -M test.metalink --metalink-language=en-US --select-file 1,3-5" << endl;
- cout << _(" Print file listing of .metalink file:") << endl;
- cout << " aria2c -M test.metalink -S --metalink-language=en-US" << endl;
-#endif // ENABLE_METALINK
- cout << endl;
- printf(_("Report bugs to %s"), "<tujikawa at users dot sourceforge dot net>");
- cout << endl;
-}
-
Strings unfoldURI(const Strings& args)
{
Strings nargs;
@@ -375,17 +97,22 @@ Strings unfoldURI(const Strings& args)
return nargs;
}
-string toBoolArg(const char* optarg)
+RequestGroupHandle createRequestGroup(const Option* op, const Strings& uris,
+ const string& ufilename = "")
{
- string arg;
- if(!optarg || string(optarg) == "") {
- arg = V_TRUE;
- } else {
- arg = optarg;
- }
- return arg;
+ RequestGroupHandle rg = new RequestGroup(op, uris);
+ SingleFileDownloadContextHandle dctx =
+ new SingleFileDownloadContext(op->getAsInt(PREF_SEGMENT_SIZE),
+ 0,
+ "",
+ ufilename);
+ dctx->setDir(op->get(PREF_DIR));
+ rg->setDownloadContext(dctx);
+ return rg;
}
+extern Option* option_processing(int argc, char* const argv[]);
+
int main(int argc, char* argv[]) {
#ifdef HAVE_WINSOCK2_H
Platform platform;
@@ -397,374 +124,7 @@ int main(int argc, char* argv[]) {
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
#endif // ENABLE_NLS
- stringstream cmdstream;
- int32_t c;
- Option* op = new Option();
- op->put(PREF_STDOUT_LOG, V_FALSE);
- op->put(PREF_DIR, ".");
- op->put(PREF_SPLIT, "1");
- op->put(PREF_DAEMON, V_FALSE);
- op->put(PREF_SEGMENT_SIZE, Util::itos((int32_t)(1024*1024)));
- op->put(PREF_HTTP_KEEP_ALIVE, V_FALSE);
- op->put(PREF_LISTEN_PORT, "-1");
- op->put(PREF_METALINK_SERVERS, "5");
- op->put(PREF_FOLLOW_TORRENT,
-#ifdef ENABLE_BITTORRENT
- V_TRUE
-#else
- V_FALSE
-#endif // ENABLE_BITTORRENT
- );
- op->put(PREF_FOLLOW_METALINK,
-#ifdef ENABLE_METALINK
- V_TRUE
-#else
- V_FALSE
-#endif // ENABLE_METALINK
- );
- op->put(PREF_RETRY_WAIT, "5");
- op->put(PREF_TIMEOUT, "60");
- op->put(PREF_DNS_TIMEOUT, "10");
- op->put(PREF_PEER_CONNECTION_TIMEOUT, "60");
- op->put(PREF_BT_TIMEOUT, "180");
- op->put(PREF_BT_REQUEST_TIMEOUT, "60");
- op->put(PREF_BT_KEEP_ALIVE_INTERVAL, "120");
- op->put(PREF_MIN_SEGMENT_SIZE, "1048576");// 1M
- op->put(PREF_MAX_TRIES, "5");
- op->put(PREF_HTTP_AUTH_SCHEME, V_BASIC);
- op->put(PREF_HTTP_PROXY_METHOD, V_TUNNEL);
- op->put(PREF_FTP_TYPE, V_BINARY);
- op->put(PREF_FTP_VIA_HTTP_PROXY, V_TUNNEL);
- op->put(PREF_AUTO_SAVE_INTERVAL, "60");
- op->put(PREF_DIRECT_FILE_MAPPING, V_TRUE);
- op->put(PREF_LOWEST_SPEED_LIMIT, "0");
- op->put(PREF_MAX_DOWNLOAD_LIMIT, "0");
- op->put(PREF_MAX_UPLOAD_LIMIT, "0");
- op->put(PREF_STARTUP_IDLE_TIME, "10");
- op->put(PREF_TRACKER_MAX_TRIES, "10");
- op->put(PREF_FILE_ALLOCATION, V_NONE);
- op->put(PREF_ALLOW_OVERWRITE, V_FALSE);
- op->put(PREF_REALTIME_CHUNK_CHECKSUM, V_TRUE);
- op->put(PREF_CHECK_INTEGRITY, V_FALSE);
- op->put(PREF_NETRC_PATH, Util::getHomeDir()+"/.netrc");
- op->put(PREF_CONTINUE, V_FALSE);
- op->put(PREF_USER_AGENT, "aria2");
- op->put(PREF_NO_NETRC, V_FALSE);
- op->put(PREF_MAX_CONCURRENT_DOWNLOADS, "5");
- op->put(PREF_DIRECT_DOWNLOAD_TIMEOUT, "15");
- op->put(PREF_FORCE_SEQUENTIAL, V_FALSE);
- op->put(PREF_AUTO_FILE_RENAMING, V_TRUE);
- op->put(PREF_PARAMETERIZED_URI, V_FALSE);
- while(1) {
- int optIndex = 0;
- int lopt;
- static struct option longOpts[] = {
-#ifdef HAVE_DAEMON
- { "daemon", no_argument, NULL, 'D' },
-#endif // HAVE_DAEMON
- { "dir", required_argument, NULL, 'd' },
- { "out", required_argument, NULL, 'o' },
- { "log", required_argument, NULL, 'l' },
- { "split", required_argument, NULL, 's' },
- { "timeout", required_argument, NULL, 't' },
- { "max-tries", required_argument, NULL, 'm' },
- { "http-proxy", required_argument, &lopt, 1 },
- { "http-user", required_argument, &lopt, 2 },
- { "http-passwd", required_argument, &lopt, 3 },
- { "http-proxy-user", required_argument, &lopt, 4 },
- { "http-proxy-passwd", required_argument, &lopt, 5 },
- { "http-auth-scheme", required_argument, &lopt, 6 },
- { "referer", required_argument, &lopt, 7 },
- { "retry-wait", required_argument, &lopt, 8 },
- { "ftp-user", required_argument, &lopt, 9 },
- { "ftp-passwd", required_argument, &lopt, 10 },
- { "ftp-type", required_argument, &lopt, 11 },
- { "ftp-pasv", no_argument, NULL, 'p' },
- { "ftp-via-http-proxy", required_argument, &lopt, 12 },
- //{ "min-segment-size", required_argument, &lopt, 13 },
- { "http-proxy-method", required_argument, &lopt, 14 },
- { "lowest-speed-limit", required_argument, &lopt, 200 },
- { "max-download-limit", required_argument, &lopt, 201 },
- { "file-allocation", required_argument, 0, 'a' },
- { "allow-overwrite", required_argument, &lopt, 202 },
-#ifdef ENABLE_MESSAGE_DIGEST
- { "check-integrity", required_argument, &lopt, 203 },
- { "realtime-chunk-checksum", required_argument, &lopt, 204 },
-#endif // ENABLE_MESSAGE_DIGEST
- { "continue", no_argument, 0, 'c' },
- { "user-agent", required_argument, 0, 'U' },
- { "no-netrc", no_argument, 0, 'n' },
- { "input-file", required_argument, 0, 'i' },
- { "max-concurrent-downloads", required_argument, 0, 'j' },
- { "load-cookies", required_argument, &lopt, 205 },
- { "force-sequential", optional_argument, 0, 'Z' },
- { "auto-file-renaming", optional_argument, &lopt, 206 },
- { "parameterized-uri", optional_argument, 0, 'P' },
-#if defined ENABLE_BITTORRENT || ENABLE_METALINK
- { "show-files", no_argument, NULL, 'S' },
- { "select-file", required_argument, &lopt, 21 },
-#endif // ENABLE_BITTORRENT || ENABLE_METALINK
-#ifdef ENABLE_BITTORRENT
- { "torrent-file", required_argument, NULL, 'T' },
- { "listen-port", required_argument, &lopt, 15 },
- { "follow-torrent", required_argument, &lopt, 16 },
- { "no-preallocation", no_argument, &lopt, 18 },
- { "direct-file-mapping", required_argument, &lopt, 19 },
- // TODO remove upload-limit.
- //{ "upload-limit", required_argument, &lopt, 20 },
- { "seed-time", required_argument, &lopt, 22 },
- { "seed-ratio", required_argument, &lopt, 23 },
- { "max-upload-limit", required_argument, &lopt, 24 },
- { "peer-id-prefix", required_argument, &lopt, 25 },
-#endif // ENABLE_BITTORRENT
-#ifdef ENABLE_METALINK
- { "metalink-file", required_argument, NULL, 'M' },
- { "metalink-servers", required_argument, NULL, 'C' },
- { "metalink-version", required_argument, &lopt, 100 },
- { "metalink-language", required_argument, &lopt, 101 },
- { "metalink-os", required_argument, &lopt, 102 },
- { "follow-metalink", required_argument, &lopt, 103 },
- { "metalink-location", required_argument, &lopt, 104 },
-#endif // ENABLE_METALINK
- { "version", no_argument, NULL, 'v' },
- { "help", no_argument, NULL, 'h' },
- { 0, 0, 0, 0 }
- };
- c = getopt_long(argc, argv, "Dd:o:l:s:pt:m:vhST:M:C:a:cU:ni:j:Z::P::", longOpts, &optIndex);
- if(c == -1) {
- break;
- }
- switch(c) {
- case 0:{
- switch(lopt) {
- case 1:
- cmdstream << PREF_HTTP_PROXY << "=" << optarg << "\n";
- break;
- case 2:
- cmdstream << PREF_HTTP_USER << "=" << optarg << "\n";
- break;
- case 3:
- cmdstream << PREF_HTTP_PASSWD << "=" << optarg << "\n";
- break;
- case 4:
- cmdstream << PREF_HTTP_PROXY_USER << "=" << optarg << "\n";
- break;
- case 5:
- cmdstream << PREF_HTTP_PROXY_PASSWD << "=" << optarg << "\n";
- break;
- case 6:
- cmdstream << PREF_HTTP_AUTH_SCHEME << "=" << optarg << "\n";
- break;
- case 7:
- cmdstream << PREF_REFERER << "=" << optarg << "\n";
- break;
- case 8:
- cmdstream << PREF_RETRY_WAIT << "=" << optarg << "\n";
- break;
- case 9:
- cmdstream << PREF_FTP_USER << "=" << optarg << "\n";
- break;
- case 10:
- cmdstream << PREF_FTP_PASSWD << "=" << optarg << "\n";
- break;
- case 11:
- cmdstream << PREF_FTP_TYPE << "=" << optarg << "\n";
- break;
- case 12:
- cmdstream << PREF_FTP_VIA_HTTP_PROXY << "=" << optarg << "\n";
- break;
- case 13:
- cmdstream << PREF_MIN_SEGMENT_SIZE << "=" << optarg << "\n";
- break;
- case 14:
- cmdstream << PREF_HTTP_PROXY_METHOD << "=" << optarg << "\n";
- break;
- case 15:
- cmdstream << PREF_LISTEN_PORT << "=" << optarg << "\n";
- break;
- case 16:
- cmdstream << PREF_FOLLOW_TORRENT << "=" << optarg << "\n";
- break;
- case 18:
- cmdstream << PREF_NO_PREALLOCATION << "=" << V_TRUE << "\n";
- break;
- case 19:
- cmdstream << PREF_DIRECT_FILE_MAPPING << "=" << optarg << "\n";
- break;
- case 21:
- cmdstream << PREF_SELECT_FILE << "=" << optarg << "\n";
- break;
- case 22:
- cmdstream << PREF_SEED_TIME << "=" << optarg << "\n";
- break;
- case 23:
- cmdstream << PREF_SEED_RATIO << "=" << optarg << "\n";
- break;
- case 24:
- cmdstream << PREF_MAX_UPLOAD_LIMIT << "=" << optarg << "\n";
- break;
- case 25:
- cmdstream << PREF_PEER_ID_PREFIX << "=" << optarg << "\n";
- case 100:
- cmdstream << PREF_METALINK_VERSION << "=" << optarg << "\n";
- break;
- case 101:
- cmdstream << PREF_METALINK_LANGUAGE << "=" << optarg << "\n";
- break;
- case 102:
- cmdstream << PREF_METALINK_OS << "=" << optarg << "\n";
- break;
- case 103:
- cmdstream << PREF_FOLLOW_METALINK << "=" << optarg << "\n";
- break;
- case 104:
- cmdstream << PREF_METALINK_LOCATION << "=" << optarg << "\n";
- break;
- case 200:
- cmdstream << PREF_LOWEST_SPEED_LIMIT << "=" << optarg << "\n";
- break;
- case 201:
- cmdstream << PREF_MAX_DOWNLOAD_LIMIT << "=" << optarg << "\n";
- break;
- case 202:
- cmdstream << PREF_ALLOW_OVERWRITE << "=" << optarg << "\n";
- break;
- case 203:
- cmdstream << PREF_CHECK_INTEGRITY << "=" << optarg << "\n";
- break;
- case 204:
- cmdstream << PREF_REALTIME_CHUNK_CHECKSUM << "=" << optarg << "\n";
- break;
- case 205:
- cmdstream << PREF_LOAD_COOKIES << "=" << optarg << "\n";
- break;
- case 206:
- cmdstream << PREF_AUTO_FILE_RENAMING << "=" << toBoolArg(optarg) << "\n";
- break;
- }
- break;
- }
-#ifdef HAVE_DAEMON
- case 'D':
- cmdstream << PREF_DAEMON << "=" << V_TRUE << "\n";
- break;
-#endif // HAVE_DAEMON
- case 'd':
- cmdstream << PREF_DIR << "=" << optarg << "\n";
- break;
- case 'o':
- cmdstream << PREF_OUT << "=" << optarg << "\n";
- break;
- case 'l':
- cmdstream << PREF_LOG << "=" << optarg << "\n";
- break;
- case 's':
- cmdstream << PREF_SPLIT << "=" << optarg << "\n";
- break;
- case 't':
- cmdstream << PREF_TIMEOUT << "=" << optarg << "\n";
- break;
- case 'm':
- cmdstream << PREF_MAX_TRIES << "=" << optarg << "\n";
- break;
- case 'p':
- cmdstream << PREF_FTP_PASV << "=" << V_TRUE << "\n";
- break;
- case 'S':
- cmdstream << PREF_SHOW_FILES << "=" << V_TRUE << "\n";
- break;
- case 'T':
- cmdstream << PREF_TORRENT_FILE << "=" << optarg << "\n";
- break;
- case 'M':
- cmdstream << PREF_METALINK_FILE << "=" << optarg << "\n";
- break;
- case 'C':
- cmdstream << PREF_METALINK_SERVERS << "=" << optarg << "\n";
- break;
- case 'a':
- cmdstream << PREF_FILE_ALLOCATION << "=" << optarg << "\n";
- break;
- case 'c':
- cmdstream << PREF_CONTINUE << "=" << V_TRUE << "\n";
- break;
- case 'U':
- cmdstream << PREF_USER_AGENT << "=" << optarg << "\n";
- break;
- case 'n':
- cmdstream << PREF_NO_NETRC << "=" << V_TRUE << "\n";
- break;
- case 'i':
- cmdstream << PREF_INPUT_FILE << "=" << optarg << "\n";
- break;
- case 'j':
- cmdstream << PREF_MAX_CONCURRENT_DOWNLOADS << "=" << optarg << "\n";
- break;
- case 'Z':
- cmdstream << PREF_FORCE_SEQUENTIAL << "=" << toBoolArg(optarg) << "\n";
- break;
- case 'P':
- cmdstream << PREF_PARAMETERIZED_URI << "=" << toBoolArg(optarg) << "\n";
- break;
- case 'v':
- showVersion();
- exit(EXIT_SUCCESS);
- case 'h':
- showUsage();
- exit(EXIT_SUCCESS);
- default:
- exit(EXIT_FAILURE);
- }
- }
-
- {
- OptionParser oparser;
- oparser.setOptionHandlers(OptionHandlerFactory::createOptionHandlers());
- string cfname = Util::getHomeDir()+"/.aria2/aria2.conf";
- ifstream cfstream(cfname.c_str());
- try {
- oparser.parse(op, cfstream);
- } catch(Exception* e) {
- cerr << "Parse error in " << cfname << endl;
- cerr << e->getMsg() << endl;
- delete e;
- exit(EXIT_FAILURE);
- }
- try {
- oparser.parse(op, cmdstream);
- } catch(Exception* e) {
- cerr << e->getMsg() << endl;
- delete e;
- exit(EXIT_FAILURE);
- }
- }
- if(op->defined(PREF_HTTP_USER)) {
- op->put(PREF_HTTP_AUTH_ENABLED, V_TRUE);
- }
- if(op->defined(PREF_HTTP_PROXY_USER)) {
- op->put(PREF_HTTP_PROXY_AUTH_ENABLED, V_TRUE);
- }
- if(
-#ifdef ENABLE_BITTORRENT
- !op->defined(PREF_TORRENT_FILE) &&
-#endif // ENABLE_BITTORRENT
-#ifdef ENABLE_METALINK
- !op->defined(PREF_METALINK_FILE) &&
-#endif // ENABLE_METALINK
- !op->defined(PREF_INPUT_FILE)) {
- if(optind == argc) {
- cerr << MSG_URI_REQUIRED << endl;
- exit(EXIT_FAILURE);
- }
- }
-#ifdef HAVE_DAEMON
- if(op->getAsBool(PREF_DAEMON)) {
- if(daemon(1, 1) < 0) {
- perror(MSG_DAEMON_FAILED);
- exit(EXIT_FAILURE);
- }
- }
-#endif // HAVE_DAEMON
+ Option* op = option_processing(argc, argv);
Strings args(argv+optind, argv+argc);
#ifdef HAVE_LIBSSL
@@ -780,7 +140,6 @@ int main(int argc, char* argv[]) {
#endif // ENABLE_METALINK
SimpleRandomizer::init();
BitfieldManFactory::setDefaultRandomizer(SimpleRandomizer::getInstance());
- FileAllocationMonitorFactory::setFactory(new ConsoleFileAllocationMonitorFactory());
if(op->getAsBool(PREF_STDOUT_LOG)) {
LogFactory::setLogFile(DEV_STDOUT);
} else if(op->get(PREF_LOG).size()) {
@@ -829,28 +188,43 @@ int main(int argc, char* argv[]) {
Util::setGlobalSignalHandler(SIGPIPE, SIG_IGN, 0);
#endif
- RequestInfo* firstReqInfo;
+ MultiUrlRequestInfo* firstReqInfo;
+ // TODO added _X for test. Please remove this later on.
#ifdef ENABLE_BITTORRENT
if(op->defined(PREF_TORRENT_FILE)) {
- firstReqInfo = new TorrentRequestInfo(op->get(PREF_TORRENT_FILE),
- op);
- Strings targetFiles;
- if(op->defined(PREF_TORRENT_FILE) && !args.empty()) {
- targetFiles = args;
+ Strings nargs;
+ if(op->get(PREF_PARAMETERIZED_URI) == V_TRUE) {
+ nargs = unfoldURI(args);
+ } else {
+ nargs = args;
+ }
+ Strings xargs;
+ ncopy(nargs.begin(), nargs.end(), op->getAsInt(PREF_SPLIT),
+ back_inserter(xargs));
+
+ RequestGroupHandle rg = new RequestGroup(op, xargs);
+ DefaultBtContextHandle btContext = new DefaultBtContext();
+ btContext->load(op->get(PREF_TORRENT_FILE));
+ if(op->defined(PREF_PEER_ID_PREFIX)) {
+ btContext->setPeerIdPrefix(op->get(PREF_PEER_ID_PREFIX));
}
- ((TorrentRequestInfo*)firstReqInfo)->setTargetFiles(targetFiles);
+ btContext->setDir(op->get(PREF_DIR));
+ rg->setDownloadContext(btContext);
+ btContext->setOwnerRequestGroup(rg.get());
+
+ RequestGroups groups;
+ groups.push_back(rg);
+ firstReqInfo = new MultiUrlRequestInfo(groups, op);
}
else
#endif // ENABLE_BITTORRENT
#ifdef ENABLE_METALINK
if(op->defined(PREF_METALINK_FILE)) {
- firstReqInfo = new MetalinkRequestInfo(op->get(PREF_METALINK_FILE),
- op);
- Strings targetFiles;
- if(op->defined(PREF_METALINK_FILE) && !args.empty()) {
- targetFiles = args;
+ RequestGroups groups = Metalink2RequestGroup(op).generate(op->get(PREF_METALINK_FILE));
+ if(groups.empty()) {
+ throw new FatalException("No files to download.");
}
- ((MetalinkRequestInfo*)firstReqInfo)->setTargetFiles(targetFiles);
+ firstReqInfo = new MultiUrlRequestInfo(groups, op);
}
else
#endif // ENABLE_METALINK
@@ -872,16 +246,15 @@ int main(int argc, char* argv[]) {
for(Strings::const_iterator itr = unfoldedURIs.begin();
itr != unfoldedURIs.end(); ++itr) {
Strings xuris;
- ncopy(itr, itr+1, op->getAsInt(PREF_SPLIT),
- back_inserter(xuris));
- RequestGroupHandle rg = new RequestGroup(xuris, op);
+ ncopy(itr, itr+1, op->getAsInt(PREF_SPLIT), back_inserter(xuris));
+ RequestGroupHandle rg = createRequestGroup(op, xuris);
groups.push_back(rg);
}
} else if(uris.size() > 0) {
Strings xuris;
ncopy(uris.begin(), uris.end(), op->getAsInt(PREF_SPLIT),
back_inserter(xuris));
- RequestGroupHandle rg = new RequestGroup(xuris, op);
+ RequestGroupHandle rg = createRequestGroup(op, xuris);
groups.push_back(rg);
}
}
@@ -901,8 +274,8 @@ int main(int argc, char* argv[]) {
itr != nargs.end(); ++itr) {
Strings xuris;
ncopy(itr, itr+1, op->getAsInt(PREF_SPLIT),
- back_inserter(xuris));
- RequestGroupHandle rg = new RequestGroup(xuris, op);
+ back_inserter(xuris));
+ RequestGroupHandle rg = createRequestGroup(op, xuris);
groups.push_back(rg);
}
firstReqInfo = new MultiUrlRequestInfo(groups, op);
@@ -910,36 +283,15 @@ int main(int argc, char* argv[]) {
Strings xargs;
ncopy(nargs.begin(), nargs.end(), op->getAsInt(PREF_SPLIT),
back_inserter(xargs));
- firstReqInfo = new MultiUrlRequestInfo(xargs, op);
+ RequestGroupHandle rg = createRequestGroup(op, xargs, op->get(PREF_OUT));
+ RequestGroups groups;
+ groups.push_back(rg);
+ firstReqInfo = new MultiUrlRequestInfo(groups, op);
}
}
- RequestInfos reqInfos;
- if(firstReqInfo) {
- reqInfos.push_front(firstReqInfo);
- }
- while(reqInfos.size()) {
- RequestInfoHandle reqInfo = reqInfos.front();
- reqInfos.pop_front();
- RequestInfos nextReqInfos = reqInfo->execute();
- copy(nextReqInfos.begin(), nextReqInfos.end(), front_inserter(reqInfos));
- /*
- if(reqInfo->isFail()) {
- exitStatus = EXIT_FAILURE;
- } else if(reqInfo->getFileInfo().checkReady()) {
- cout << _("Now verifying checksum.\n"
- "This may take some time depending on your PC environment"
- " and the size of file.") << endl;
- if(reqInfo->getFileInfo().check()) {
- cout << _("checksum OK.") << endl;
- } else {
- // TODO
- cout << _("checksum ERROR.") << endl;
- exitStatus = EXIT_FAILURE;
- }
- }
- */
- }
+ firstReqInfo->execute();
+
} catch(Exception* ex) {
cerr << EX_EXCEPTION_CAUGHT << "\n" << ex->getMsg() << endl;
delete ex;
diff --git a/src/messageDigest.h b/src/messageDigest.h
index 7bf37685..612e0920 100644
--- a/src/messageDigest.h
+++ b/src/messageDigest.h
@@ -36,7 +36,7 @@
#define _D_MESSAGE_DIGEST_H_
#include "common.h"
-#include "FatalException.h"
+#include "DlAbortEx.h"
#include <map>
#ifdef HAVE_LIBSSL
@@ -94,7 +94,7 @@ public:
{
DigestAlgoMap::const_iterator itr = digestAlgos.find(algostring);
if(itr == digestAlgos.end()) {
- throw new FatalException("Digest algorithm %s is not supported.", algostring.c_str());
+ throw new DlAbortEx("Digest algorithm %s is not supported.", algostring.c_str());
}
return (*itr).second;
}
diff --git a/src/option_processing.cc b/src/option_processing.cc
new file mode 100644
index 00000000..92c4b2f0
--- /dev/null
+++ b/src/option_processing.cc
@@ -0,0 +1,434 @@
+/* <!-- 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 "common.h"
+#include "Option.h"
+#include "prefs.h"
+#include "OptionParser.h"
+#include "OptionHandlerFactory.h"
+#include "Util.h"
+#include "message.h"
+#include <fstream>
+#include <sstream>
+
+extern char* optarg;
+extern int optind, opterr, optopt;
+#include <getopt.h>
+
+extern void showVersion();
+extern void showUsage();
+
+static string toBoolArg(const char* optarg)
+{
+ string arg;
+ if(!optarg || string(optarg) == "") {
+ arg = V_TRUE;
+ } else {
+ arg = optarg;
+ }
+ return arg;
+}
+
+Option* option_processing(int argc, char* const argv[])
+{
+ stringstream cmdstream;
+ int32_t c;
+ Option* op = new Option();
+ op->put(PREF_STDOUT_LOG, V_FALSE);
+ op->put(PREF_DIR, ".");
+ op->put(PREF_SPLIT, "1");
+ op->put(PREF_DAEMON, V_FALSE);
+ op->put(PREF_SEGMENT_SIZE, Util::itos((int32_t)(1024*1024)));
+ op->put(PREF_HTTP_KEEP_ALIVE, V_FALSE);
+ op->put(PREF_LISTEN_PORT, "-1");
+ op->put(PREF_METALINK_SERVERS, "5");
+ op->put(PREF_FOLLOW_TORRENT,
+#ifdef ENABLE_BITTORRENT
+ V_TRUE
+#else
+ V_FALSE
+#endif // ENABLE_BITTORRENT
+ );
+ op->put(PREF_FOLLOW_METALINK,
+#ifdef ENABLE_METALINK
+ V_TRUE
+#else
+ V_FALSE
+#endif // ENABLE_METALINK
+ );
+ op->put(PREF_RETRY_WAIT, "5");
+ op->put(PREF_TIMEOUT, "60");
+ op->put(PREF_DNS_TIMEOUT, "10");
+ op->put(PREF_PEER_CONNECTION_TIMEOUT, "60");
+ op->put(PREF_BT_TIMEOUT, "180");
+ op->put(PREF_BT_REQUEST_TIMEOUT, "60");
+ op->put(PREF_BT_KEEP_ALIVE_INTERVAL, "120");
+ op->put(PREF_MIN_SEGMENT_SIZE, "1048576");// 1M
+ op->put(PREF_MAX_TRIES, "5");
+ op->put(PREF_HTTP_AUTH_SCHEME, V_BASIC);
+ op->put(PREF_HTTP_PROXY_METHOD, V_TUNNEL);
+ op->put(PREF_FTP_TYPE, V_BINARY);
+ op->put(PREF_FTP_VIA_HTTP_PROXY, V_TUNNEL);
+ op->put(PREF_AUTO_SAVE_INTERVAL, "60");
+ op->put(PREF_DIRECT_FILE_MAPPING, V_TRUE);
+ op->put(PREF_LOWEST_SPEED_LIMIT, "0");
+ op->put(PREF_MAX_DOWNLOAD_LIMIT, "0");
+ op->put(PREF_MAX_UPLOAD_LIMIT, "0");
+ op->put(PREF_STARTUP_IDLE_TIME, "10");
+ op->put(PREF_TRACKER_MAX_TRIES, "10");
+ op->put(PREF_FILE_ALLOCATION, V_NONE);
+ op->put(PREF_ALLOW_OVERWRITE, V_FALSE);
+ op->put(PREF_REALTIME_CHUNK_CHECKSUM, V_TRUE);
+ op->put(PREF_CHECK_INTEGRITY, V_FALSE);
+ op->put(PREF_NETRC_PATH, Util::getHomeDir()+"/.netrc");
+ op->put(PREF_CONTINUE, V_FALSE);
+ op->put(PREF_USER_AGENT, "aria2");
+ op->put(PREF_NO_NETRC, V_FALSE);
+ op->put(PREF_MAX_CONCURRENT_DOWNLOADS, "5");
+ op->put(PREF_DIRECT_DOWNLOAD_TIMEOUT, "15");
+ op->put(PREF_FORCE_SEQUENTIAL, V_FALSE);
+ op->put(PREF_AUTO_FILE_RENAMING, V_TRUE);
+ op->put(PREF_PARAMETERIZED_URI, V_FALSE);
+ while(1) {
+ int optIndex = 0;
+ int lopt;
+ static struct option longOpts[] = {
+#ifdef HAVE_DAEMON
+ { "daemon", no_argument, NULL, 'D' },
+#endif // HAVE_DAEMON
+ { "dir", required_argument, NULL, 'd' },
+ { "out", required_argument, NULL, 'o' },
+ { "log", required_argument, NULL, 'l' },
+ { "split", required_argument, NULL, 's' },
+ { "timeout", required_argument, NULL, 't' },
+ { "max-tries", required_argument, NULL, 'm' },
+ { "http-proxy", required_argument, &lopt, 1 },
+ { "http-user", required_argument, &lopt, 2 },
+ { "http-passwd", required_argument, &lopt, 3 },
+ { "http-proxy-user", required_argument, &lopt, 4 },
+ { "http-proxy-passwd", required_argument, &lopt, 5 },
+ { "http-auth-scheme", required_argument, &lopt, 6 },
+ { "referer", required_argument, &lopt, 7 },
+ { "retry-wait", required_argument, &lopt, 8 },
+ { "ftp-user", required_argument, &lopt, 9 },
+ { "ftp-passwd", required_argument, &lopt, 10 },
+ { "ftp-type", required_argument, &lopt, 11 },
+ { "ftp-pasv", no_argument, NULL, 'p' },
+ { "ftp-via-http-proxy", required_argument, &lopt, 12 },
+ //{ "min-segment-size", required_argument, &lopt, 13 },
+ { "http-proxy-method", required_argument, &lopt, 14 },
+ { "lowest-speed-limit", required_argument, &lopt, 200 },
+ { "max-download-limit", required_argument, &lopt, 201 },
+ { "file-allocation", required_argument, 0, 'a' },
+ { "allow-overwrite", required_argument, &lopt, 202 },
+#ifdef ENABLE_MESSAGE_DIGEST
+ { "check-integrity", required_argument, &lopt, 203 },
+ { "realtime-chunk-checksum", required_argument, &lopt, 204 },
+#endif // ENABLE_MESSAGE_DIGEST
+ { "continue", no_argument, 0, 'c' },
+ { "user-agent", required_argument, 0, 'U' },
+ { "no-netrc", no_argument, 0, 'n' },
+ { "input-file", required_argument, 0, 'i' },
+ { "max-concurrent-downloads", required_argument, 0, 'j' },
+ { "load-cookies", required_argument, &lopt, 205 },
+ { "force-sequential", optional_argument, 0, 'Z' },
+ { "auto-file-renaming", optional_argument, &lopt, 206 },
+ { "parameterized-uri", optional_argument, 0, 'P' },
+#if defined ENABLE_BITTORRENT || ENABLE_METALINK
+ { "show-files", no_argument, NULL, 'S' },
+ { "select-file", required_argument, &lopt, 21 },
+#endif // ENABLE_BITTORRENT || ENABLE_METALINK
+#ifdef ENABLE_BITTORRENT
+ { "torrent-file", required_argument, NULL, 'T' },
+ { "listen-port", required_argument, &lopt, 15 },
+ { "follow-torrent", required_argument, &lopt, 16 },
+ { "no-preallocation", no_argument, &lopt, 18 },
+ { "direct-file-mapping", required_argument, &lopt, 19 },
+ // TODO remove upload-limit.
+ //{ "upload-limit", required_argument, &lopt, 20 },
+ { "seed-time", required_argument, &lopt, 22 },
+ { "seed-ratio", required_argument, &lopt, 23 },
+ { "max-upload-limit", required_argument, &lopt, 24 },
+ { "peer-id-prefix", required_argument, &lopt, 25 },
+#endif // ENABLE_BITTORRENT
+#ifdef ENABLE_METALINK
+ { "metalink-file", required_argument, NULL, 'M' },
+ { "metalink-servers", required_argument, NULL, 'C' },
+ { "metalink-version", required_argument, &lopt, 100 },
+ { "metalink-language", required_argument, &lopt, 101 },
+ { "metalink-os", required_argument, &lopt, 102 },
+ { "follow-metalink", required_argument, &lopt, 103 },
+ { "metalink-location", required_argument, &lopt, 104 },
+#endif // ENABLE_METALINK
+ { "version", no_argument, NULL, 'v' },
+ { "help", no_argument, NULL, 'h' },
+ { 0, 0, 0, 0 }
+ };
+ c = getopt_long(argc, argv, "Dd:o:l:s:pt:m:vhST:M:C:a:cU:ni:j:Z::P::", longOpts, &optIndex);
+ if(c == -1) {
+ break;
+ }
+ switch(c) {
+ case 0:{
+ switch(lopt) {
+ case 1:
+ cmdstream << PREF_HTTP_PROXY << "=" << optarg << "\n";
+ break;
+ case 2:
+ cmdstream << PREF_HTTP_USER << "=" << optarg << "\n";
+ break;
+ case 3:
+ cmdstream << PREF_HTTP_PASSWD << "=" << optarg << "\n";
+ break;
+ case 4:
+ cmdstream << PREF_HTTP_PROXY_USER << "=" << optarg << "\n";
+ break;
+ case 5:
+ cmdstream << PREF_HTTP_PROXY_PASSWD << "=" << optarg << "\n";
+ break;
+ case 6:
+ cmdstream << PREF_HTTP_AUTH_SCHEME << "=" << optarg << "\n";
+ break;
+ case 7:
+ cmdstream << PREF_REFERER << "=" << optarg << "\n";
+ break;
+ case 8:
+ cmdstream << PREF_RETRY_WAIT << "=" << optarg << "\n";
+ break;
+ case 9:
+ cmdstream << PREF_FTP_USER << "=" << optarg << "\n";
+ break;
+ case 10:
+ cmdstream << PREF_FTP_PASSWD << "=" << optarg << "\n";
+ break;
+ case 11:
+ cmdstream << PREF_FTP_TYPE << "=" << optarg << "\n";
+ break;
+ case 12:
+ cmdstream << PREF_FTP_VIA_HTTP_PROXY << "=" << optarg << "\n";
+ break;
+ case 13:
+ cmdstream << PREF_MIN_SEGMENT_SIZE << "=" << optarg << "\n";
+ break;
+ case 14:
+ cmdstream << PREF_HTTP_PROXY_METHOD << "=" << optarg << "\n";
+ break;
+ case 15:
+ cmdstream << PREF_LISTEN_PORT << "=" << optarg << "\n";
+ break;
+ case 16:
+ cmdstream << PREF_FOLLOW_TORRENT << "=" << optarg << "\n";
+ break;
+ case 18:
+ cmdstream << PREF_NO_PREALLOCATION << "=" << V_TRUE << "\n";
+ break;
+ case 19:
+ cmdstream << PREF_DIRECT_FILE_MAPPING << "=" << optarg << "\n";
+ break;
+ case 21:
+ cmdstream << PREF_SELECT_FILE << "=" << optarg << "\n";
+ break;
+ case 22:
+ cmdstream << PREF_SEED_TIME << "=" << optarg << "\n";
+ break;
+ case 23:
+ cmdstream << PREF_SEED_RATIO << "=" << optarg << "\n";
+ break;
+ case 24:
+ cmdstream << PREF_MAX_UPLOAD_LIMIT << "=" << optarg << "\n";
+ break;
+ case 25:
+ cmdstream << PREF_PEER_ID_PREFIX << "=" << optarg << "\n";
+ case 100:
+ cmdstream << PREF_METALINK_VERSION << "=" << optarg << "\n";
+ break;
+ case 101:
+ cmdstream << PREF_METALINK_LANGUAGE << "=" << optarg << "\n";
+ break;
+ case 102:
+ cmdstream << PREF_METALINK_OS << "=" << optarg << "\n";
+ break;
+ case 103:
+ cmdstream << PREF_FOLLOW_METALINK << "=" << optarg << "\n";
+ break;
+ case 104:
+ cmdstream << PREF_METALINK_LOCATION << "=" << optarg << "\n";
+ break;
+ case 200:
+ cmdstream << PREF_LOWEST_SPEED_LIMIT << "=" << optarg << "\n";
+ break;
+ case 201:
+ cmdstream << PREF_MAX_DOWNLOAD_LIMIT << "=" << optarg << "\n";
+ break;
+ case 202:
+ cmdstream << PREF_ALLOW_OVERWRITE << "=" << optarg << "\n";
+ break;
+ case 203:
+ cmdstream << PREF_CHECK_INTEGRITY << "=" << optarg << "\n";
+ break;
+ case 204:
+ cmdstream << PREF_REALTIME_CHUNK_CHECKSUM << "=" << optarg << "\n";
+ break;
+ case 205:
+ cmdstream << PREF_LOAD_COOKIES << "=" << optarg << "\n";
+ break;
+ case 206:
+ cmdstream << PREF_AUTO_FILE_RENAMING << "=" << toBoolArg(optarg) << "\n";
+ break;
+ }
+ break;
+ }
+#ifdef HAVE_DAEMON
+ case 'D':
+ cmdstream << PREF_DAEMON << "=" << V_TRUE << "\n";
+ break;
+#endif // HAVE_DAEMON
+ case 'd':
+ cmdstream << PREF_DIR << "=" << optarg << "\n";
+ break;
+ case 'o':
+ cmdstream << PREF_OUT << "=" << optarg << "\n";
+ break;
+ case 'l':
+ cmdstream << PREF_LOG << "=" << optarg << "\n";
+ break;
+ case 's':
+ cmdstream << PREF_SPLIT << "=" << optarg << "\n";
+ break;
+ case 't':
+ cmdstream << PREF_TIMEOUT << "=" << optarg << "\n";
+ break;
+ case 'm':
+ cmdstream << PREF_MAX_TRIES << "=" << optarg << "\n";
+ break;
+ case 'p':
+ cmdstream << PREF_FTP_PASV << "=" << V_TRUE << "\n";
+ break;
+ case 'S':
+ cmdstream << PREF_SHOW_FILES << "=" << V_TRUE << "\n";
+ break;
+ case 'T':
+ cmdstream << PREF_TORRENT_FILE << "=" << optarg << "\n";
+ break;
+ case 'M':
+ cmdstream << PREF_METALINK_FILE << "=" << optarg << "\n";
+ break;
+ case 'C':
+ cmdstream << PREF_METALINK_SERVERS << "=" << optarg << "\n";
+ break;
+ case 'a':
+ cmdstream << PREF_FILE_ALLOCATION << "=" << optarg << "\n";
+ break;
+ case 'c':
+ cmdstream << PREF_CONTINUE << "=" << V_TRUE << "\n";
+ break;
+ case 'U':
+ cmdstream << PREF_USER_AGENT << "=" << optarg << "\n";
+ break;
+ case 'n':
+ cmdstream << PREF_NO_NETRC << "=" << V_TRUE << "\n";
+ break;
+ case 'i':
+ cmdstream << PREF_INPUT_FILE << "=" << optarg << "\n";
+ break;
+ case 'j':
+ cmdstream << PREF_MAX_CONCURRENT_DOWNLOADS << "=" << optarg << "\n";
+ break;
+ case 'Z':
+ cmdstream << PREF_FORCE_SEQUENTIAL << "=" << toBoolArg(optarg) << "\n";
+ break;
+ case 'P':
+ cmdstream << PREF_PARAMETERIZED_URI << "=" << toBoolArg(optarg) << "\n";
+ break;
+ case 'v':
+ showVersion();
+ exit(EXIT_SUCCESS);
+ case 'h':
+ showUsage();
+ exit(EXIT_SUCCESS);
+ default:
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ {
+ OptionParser oparser;
+ oparser.setOptionHandlers(OptionHandlerFactory::createOptionHandlers());
+ string cfname = Util::getHomeDir()+"/.aria2/aria2.conf";
+ ifstream cfstream(cfname.c_str());
+ try {
+ oparser.parse(op, cfstream);
+ } catch(Exception* e) {
+ cerr << "Parse error in " << cfname << endl;
+ cerr << e->getMsg() << endl;
+ delete e;
+ exit(EXIT_FAILURE);
+ }
+ try {
+ oparser.parse(op, cmdstream);
+ } catch(Exception* e) {
+ cerr << e->getMsg() << endl;
+ delete e;
+ exit(EXIT_FAILURE);
+ }
+ }
+ if(op->defined(PREF_HTTP_USER)) {
+ op->put(PREF_HTTP_AUTH_ENABLED, V_TRUE);
+ }
+ if(op->defined(PREF_HTTP_PROXY_USER)) {
+ op->put(PREF_HTTP_PROXY_AUTH_ENABLED, V_TRUE);
+ }
+ if(
+#ifdef ENABLE_BITTORRENT
+ !op->defined(PREF_TORRENT_FILE) &&
+#endif // ENABLE_BITTORRENT
+#ifdef ENABLE_METALINK
+ !op->defined(PREF_METALINK_FILE) &&
+#endif // ENABLE_METALINK
+ !op->defined(PREF_INPUT_FILE)) {
+ if(optind == argc) {
+ cerr << MSG_URI_REQUIRED << endl;
+ exit(EXIT_FAILURE);
+ }
+ }
+#ifdef HAVE_DAEMON
+ if(op->getAsBool(PREF_DAEMON)) {
+ if(daemon(1, 1) < 0) {
+ perror(MSG_DAEMON_FAILED);
+ exit(EXIT_FAILURE);
+ }
+ }
+#endif // HAVE_DAEMON
+ return op;
+}
diff --git a/src/version_usage.cc b/src/version_usage.cc
new file mode 100644
index 00000000..b246e720
--- /dev/null
+++ b/src/version_usage.cc
@@ -0,0 +1,305 @@
+/* <!-- 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 "common.h"
+#include "FeatureConfig.h"
+#include "messageDigest.h"
+
+void showVersion() {
+ cout << PACKAGE << _(" version ") << PACKAGE_VERSION << endl;
+ cout << "**Configuration**" << endl;
+ cout << FeatureConfig::getInstance()->getConfigurationSummary();
+#ifdef ENABLE_MESSAGE_DIGEST
+ cout << "message digest algorithms: " << MessageDigestContext::getSupportedAlgoString() << endl;
+#endif // ENABLE_MESSAGE_DIGEST
+ cout << endl;
+ cout << "Copyright (C) 2006, 2007 Tatsuhiro Tsujikawa" << endl;
+ cout << endl;
+ cout <<
+ _("This program is free software; you can redistribute it and/or modify\n"
+ "it under the terms of the GNU General Public License as published by\n"
+ "the Free Software Foundation; either version 2 of the License, or\n"
+ "(at your option) any later version.\n"
+ "\n"
+ "This program is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+ "GNU General Public License for more details.\n"
+ "\n"
+ "You should have received a copy of the GNU General Public License\n"
+ "along with this program; if not, write to the Free Software\n"
+ "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n");
+ cout << endl;
+ cout << _("Contact Info:") << endl;
+ cout << "Tatsuhiro Tsujikawa <tujikawa at users dot sourceforge dot net>" << endl;
+ cout << endl;
+
+}
+
+void showUsage() {
+ printf(_("Usage: %s [options] URL ...\n"), PACKAGE_NAME);
+#ifdef ENABLE_BITTORRENT
+ printf(_(" %s [options] -T TORRENT_FILE URL ...\n"), PACKAGE_NAME);
+#endif // ENABLE_BITTORRENT
+#ifdef ENABLE_METALINK
+ printf(_(" %s [options] -M METALINK_FILE\n"), PACKAGE_NAME);
+#endif // ENABLE_METALINK
+ cout << endl;
+ cout << _("Options:") << endl;
+ cout << _(" -d, --dir=DIR The directory to store the downloaded file.") << endl;
+ cout << _(" -o, --out=FILE The file name of the downloaded file.") << endl;
+ cout << _(" -l, --log=LOG The file name of the log file. If '-' is\n"
+ " specified, log is written to stdout.") << endl;
+#ifdef HAVE_DAEMON
+ cout << _(" -D, --daemon Run as daemon.") << endl;
+#endif // HAVE_DAEMON
+ cout << _(" -s, --split=N Download a file using N connections. N must be\n"
+ " between 1 and 5. This option affects all URLs.\n"
+ " Thus, aria2 connects to each URL with\n"
+ " N connections.\n"
+ " Default: 1") << endl;
+ cout << _(" --retry-wait=SEC Set the seconds to wait to retry after an error\n"
+ " has occured. Specify a value between 0 and 60.\n"
+ " Default: 5") << endl;
+ cout << _(" -t, --timeout=SEC Set timeout in seconds. Default: 60") << endl;
+ cout << _(" -m, --max-tries=N Set number of tries. 0 means unlimited.\n"
+ " Default: 5") << endl;
+ /*
+ cout << _(" --min-segment-size=SIZE[K|M] Set minimum segment size. You can append\n"
+ " K or M(1K = 1024, 1M = 1024K). This\n"
+ " value must be greater than or equal to\n"
+ " 1024. Default: 1M") << endl;
+ */
+ cout << _(" --http-proxy=HOST:PORT Use HTTP proxy server. This affects all URLs.") << endl;
+ cout << _(" --http-user=USER Set HTTP user. This affects all URLs.") << endl;
+ cout << _(" --http-passwd=PASSWD Set HTTP password. This affects all URLs.") << endl;
+ cout << _(" --http-proxy-user=USER Set HTTP proxy user. This affects all URLs.") << endl;
+ cout << _(" --http-proxy-passwd=PASSWD Set HTTP proxy password. This affects all URLs.") << endl;
+ cout << _(" --http-proxy-method=METHOD Set the method to use in proxy request.\n"
+ " METHOD is either 'get' or 'tunnel'.\n"
+ " Default: tunnel") << endl;
+ cout << _(" --http-auth-scheme=SCHEME Set HTTP authentication scheme. Currently, basic\n"
+ " is the only supported scheme.\n"
+ " Default: basic") << endl;
+ cout << _(" --referer=REFERER Set Referer. This affects all URLs.") << endl;
+ cout << _(" --ftp-user=USER Set FTP user. This affects all URLs.\n"
+ " Default: anonymous") << endl;
+ cout << _(" --ftp-passwd=PASSWD Set FTP password. This affects all URLs.\n"
+ " Default: ARIA2USER@") << endl;
+ cout << _(" --ftp-type=TYPE Set FTP transfer type. TYPE is either 'binary'\n"
+ " or 'ascii'.\n"
+ " Default: binary") << endl;
+ cout << _(" -p, --ftp-pasv Use passive mode in FTP.") << endl;
+ cout << _(" --ftp-via-http-proxy=METHOD Use HTTP proxy in FTP. METHOD is either 'get' or\n"
+ " 'tunnel'.\n"
+ " Default: tunnel") << endl;
+ cout << _(" --lowest-speed-limit=SPEED Close connection if download speed is lower than\n"
+ " or equal to this value(bytes per sec).\n"
+ " 0 means aria2 does not have a lowest speed limit.\n"
+ " You can append K or M(1K = 1024, 1M = 1024K).\n"
+
+ " This option does not affect BitTorrent downloads.\n"
+ " Default: 0") << endl;
+ cout << _(" --max-download-limit=SPEED Set max download speed in bytes per sec.\n"
+ " 0 means unrestricted.\n"
+ " You can append K or M(1K = 1024, 1M = 1024K).\n"
+ " Default: 0") << endl;
+ cout << _(" --file-allocation=METHOD Specify file allocation method. METHOD is either\n"
+ " 'none' or 'prealloc'. 'none' doesn't pre-allocate\n"
+ " file space. 'prealloc' pre-allocates file space\n"
+ " before download begins. This may take some time\n"
+ " depending on the size of the file.\n"
+ " Default: none") << endl;
+ cout << _(" --allow-overwrite=true|false If false, aria2 doesn't download a file which\n"
+ " already exists but the corresponding .aria2 file\n"
+ " doesn't exist.\n"
+ " Default: false") << endl;
+ cout << _(" -Z, --force-sequential[=true|false] Fetch URIs in the command-line sequentially\n"
+ " and download each URI in a separate session, like\n"
+ " the usual command-line download utilities.\n"
+ " Default: false") << endl;
+ cout << _(" --auto-file-renaming[=true|false] Rename file name if the same file already\n"
+ " exists. This option works only in http(s)/ftp\n"
+ " download.\n"
+ " The new file name has a dot and a number(1..9999)\n"
+ " appended.\n"
+ " Default: true") << endl;
+ cout << _(" -P, --parameterized-uri[=true|false] Enable parameterized URI support.\n"
+ " You can specify set of parts:\n"
+ " http://{sv1,sv2,sv3}/foo.iso\n"
+ " Also you can specify numeric sequences with step\n"
+ " counter:\n"
+ " http://host/image[000-100:2].img\n"
+ " A step counter can be omitted.\n"
+ " If all URIs do not point to the same file, such\n"
+ " as the second example above, -Z option is\n"
+ " required.\n"
+ " Default: false") << endl;
+#ifdef ENABLE_MESSAGE_DIGEST
+ cout << _(" --check-integrity=true|false Check file integrity by validating piece hash.\n"
+ " This option only affects in BitTorrent downloads\n"
+ " and Metalink downloads with chunk checksums.\n"
+ " Use this option to re-download a damaged portion\n"
+ " of a file.\n"
+ " You may need to specify --allow-overwrite=true\n"
+ " if the .aria2 file doesn't exist.\n"
+ " Default: false") << endl;
+ cout << _(" --realtime-chunk-checksum=true|false Validate chunk checksum while\n"
+ " downloading a file in Metalink mode. This option\n"
+ " on affects Metalink mode with chunk checksums.\n"
+ " Default: true") << endl;
+#endif // ENABLE_MESSAGE_DIGEST
+ cout << _(" -c, --continue Continue downloading a partially downloaded\n"
+ " file. Use this option to resume a download\n"
+ " started by a web browser or another program\n"
+ " which downloads files sequentially from the\n"
+ " beginning. Currently this option is only\n"
+ " applicable to http(s)/ftp downloads.") << endl;
+ cout << _(" -U, --user-agent=USER_AGENT Set user agent for http(s) downloads.") << endl;
+ cout << _(" -n, --no-netrc Disables netrc support.") << endl;
+ cout << _(" -i, --input-file=FILE Downloads URIs found in FILE. You can specify\n"
+ " multiple URIs for a single entity: separate\n"
+ " URIs on a single line using the TAB character.\n"
+ " Reads input from stdin when '-' is specified.") << endl;
+ cout << _(" -j, --max-concurrent-downloads=N Set maximum number of concurrent downloads.\n"
+ " It should be used with the -i option.\n"
+ " Default: 5") << endl;
+ cout << _(" --load-cookies=FILE Load cookies from FILE. The format of FILE is\n"
+ " the same used by Netscape and Mozilla.") << endl;
+#if defined ENABLE_BITTORRENT || ENABLE_METALINK
+ cout << _(" -S, --show-files Print file listing of .torrent or .metalink file\n"
+ " and exit.") << endl;
+ cout << _(" --select-file=INDEX... Set file to download by specifing its index.\n"
+ " You can find the file index using the\n"
+ " --show-files option. Multiple indexes can be\n"
+ " specified by using ',', for example: \"3,6\".\n"
+ " You can also use '-' to specify a range: \"1-5\".\n"
+ " ',' and '-' can be used together.\n"
+ " When used with the -M option, index may vary\n"
+ " depending on the query(see --metalink-* options).") << endl;
+#endif // ENABLE_BITTORRENT || ENABLE_METALINK
+#ifdef ENABLE_BITTORRENT
+ cout << _(" -T, --torrent-file=TORRENT_FILE The path to the .torrent file.") << endl;
+ cout << _(" --follow-torrent=true|false Set to false to prevent aria2 from\n"
+ " entering BitTorrent mode even if the filename of\n"
+ " the downloaded file ends with .torrent.\n"
+ " Default: true") << endl;
+ cout << _(" --direct-file-mapping=true|false Directly read from and write to each file\n"
+ " mentioned in .torrent file.\n"
+ " Default: true") << endl;
+ cout << _(" --listen-port=PORT Set TCP port number for BitTorrent downloads.\n"
+ " Default: 6881-6999") << endl;
+ cout << _(" --max-upload-limit=SPEED Set max upload speed in bytes per sec.\n"
+ " 0 means unrestricted.\n"
+ " You can append K or M(1K = 1024, 1M = 1024K).\n"
+ " Default: 0") << endl;
+ cout << _(" --seed-time=MINUTES Specify seeding time in minutes. Also see the\n"
+ " --seed-ratio option.") << endl;
+ cout << _(" --seed-ratio=RATIO Specify share ratio. Seed completed torrents\n"
+ " until share ratio reaches RATIO. 1.0 is\n"
+ " encouraged. If --seed-time option is specified\n"
+ " along with this option, seeding ends when at\n"
+ " least one of the conditions is satisfied.") << endl;
+ cout << _(" --peer-id-prefix=PEERI_ID_PREFIX Specify the prefix of peer ID. The peer ID in\n"
+ " in BitTorrent is 20 byte length. If more than 20\n"
+ " bytes are specified, only first 20\n"
+ " bytes are used. If less than 20 bytes are\n"
+ " specified, the random alphabet characters are\n"
+ " added to make it's length 20 bytes.\n"
+ " Default: -aria2-") << endl;
+#endif // ENABLE_BITTORRENT
+#ifdef ENABLE_METALINK
+ cout << _(" -M, --metalink-file=METALINK_FILE The file path to the .metalink file.") << endl;
+ cout << _(" -C, --metalink-servers=NUM_SERVERS The number of servers to connect to\n"
+ " simultaneously.\n"
+ " Default: 5") << endl;
+ cout << _(" --metalink-version=VERSION The version of the file to download.") << endl;
+ cout << _(" --metalink-language=LANGUAGE The language of the file to download.") << endl;
+ cout << _(" --metalink-os=OS The operating system of the file to download.") << endl;
+ cout << _(" --metalink-location=LOCATION The location of the prefered server.") << endl;
+ cout << _(" --follow-metalink=true|false Set to false to prevent aria2 from\n"
+ " entering Metalink mode even if the filename of\n"
+ " the downloaded file ends with .metalink.\n"
+ " Default: true") << endl;
+#endif // ENABLE_METALINK
+ cout << _(" -v, --version Print the version number and exit.") << endl;
+ cout << _(" -h, --help Print this message and exit.") << endl;
+ cout << endl;
+ cout << "URL:" << endl;
+ cout << _(" You can specify multiple URLs. All URLs must point to the same file\n"
+ " or downloading will fail.") << endl;
+ cout << endl;
+ cout << _("Examples:") << endl;
+ cout << _(" Download a file using 1 connection:") << endl;
+ cout << " aria2c http://AAA.BBB.CCC/file.zip" << endl;
+ cout << _(" Download a file using 2 connections:") << endl;
+ cout << " aria2c -s 2 http://AAA.BBB.CCC/file.zip" << endl;
+ cout << _(" Download a file using 2 connections, each connects to a different server:") << endl;
+ cout << " aria2c http://AAA.BBB.CCC/file.zip http://DDD.EEE.FFF/GGG/file.zip" << endl;
+ cout << _(" You can mix up different protocols:") << endl;
+ cout << " aria2c http://AAA.BBB.CCC/file.zip ftp://DDD.EEE.FFF/GGG/file.zip" << endl;
+ cout << _(" Parameterized URI:") << endl;
+ cout << " aria2c -P http://{server1,server2,server3}/file.iso" << endl;
+ cout << _(" Parameterized URI. -Z option is required in this case:") << endl;
+ cout << " aria2c -P -Z http://host/file[001-100:2].img" << endl;
+#ifdef ENABLE_BITTORRENT
+ cout << endl;
+ cout << _(" Download a torrent:") << endl;
+ cout << " aria2c -o test.torrent http://AAA.BBB.CCC/file.torrent" << endl;
+ cout << _(" Download a torrent using a local .torrent file:") << endl;
+ cout << " aria2c -T test.torrent" << endl;
+ cout << _(" Download only selected files:") << endl;
+ cout << " aria2c -T test.torrent dir/file1.zip dir/file2.zip" << endl;
+ cout << _(" Print file listing of .torrent file:") << endl;
+ cout << " aria2c -T test.torrent -S" << endl;
+#endif // ENABLE_BITTORRENT
+#ifdef ENABLE_METALINK
+ cout << endl;
+ cout << _(" Metalink downloading:") << endl;
+ cout << " aria2c http://AAA.BBB.CCC/file.metalink" << endl;
+ cout << _(" Download a file using local .metalink file:") << endl;
+ cout << " aria2c -M test.metalink" << endl;
+ cout << _(" Metalink downloading with preferences:") << endl;
+ cout << " aria2c -M test.metalink --metalink-version=1.1.1 --metalink-language=en-US" << endl;
+ cout << _(" Download only selected files:") << endl;
+ cout << " aria2c -M test.metalink --metalink-language=en-US dir/file1.zip dir/file2.zip" << endl;
+ cout << _(" Download only selected files using index:") << endl;
+ cout << " aria2c -M test.metalink --metalink-language=en-US --select-file 1,3-5" << endl;
+ cout << _(" Print file listing of .metalink file:") << endl;
+ cout << " aria2c -M test.metalink -S --metalink-language=en-US" << endl;
+#endif // ENABLE_METALINK
+ cout << endl;
+ printf(_("Report bugs to %s"), "<tujikawa at users dot sourceforge dot net>");
+ cout << endl;
+}