mirror of https://github.com/aria2/aria2
2006-09-19 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
To rewrite segment download mechanism for HTTP/FTP download. Use BitfieldMan to manage segment download. * src/HttpResponseCommand.h (executeInternal): Pass the reference of segment. * src/AbstractCommand.cc (prepareForRetry): Call segmentMan->cancelSegment here. (onAbort): Call segmentMan->cancelSegment here. * src/HttpDownloadCommand.cc (prepareForNextSegment): New function. * src/DownloadEngineFactory.cc (newConsoleEngine): Removed splitter. (newTorrentConsoleEngine): Removed splitter. * src/Request.h (segment): Renamed from seg. * src/FtpInitiateConnectionCommand.h (executeInternal): Pass the reference of segment. * src/AbstractCommand.h (executeInternal): Pass the reference of segment. * src/pref.h (PREF_SEGMENT_SIZE): New definition. * src/HttpProxyRequestCommand.h (executeInternal): Pass the reference of segment. * src/HttpResponseCommand.cc (checkResponse): Allowed status 206 when a request range starts 0. (handleDefaultEncoding): Rewritten the code related to Segment. (handleOtherEncoding): Rewritten the code related to Segment. * src/SegmentMan.h (SegmentEntry): New class. (SegmentEntries): New type definition. (bitfield): New variable. (usedSegmentEntries): New variable. (onNullBitfield): New function. (checkoutSegment): New function. (segments): Removed. (splitter): Removed. (unregisterId): Removed. (getSegment): New function(overload) (getDownloadedSize): Removed. (cancelSegment): New function. (completeSegment): New function. (initBitfield): New function. (hasSegment): New function. (getDownloadLength): New function. * src/BitfieldMan.h (getStartIndex): New function. (getEndIndex): New function. (getMissingUnusedIndex): New function(overload). (getSparseMissingUnusedIndex): New function. * src/BitfieldMan.cc (getMissingIndexRandomly): Handle the last byte of bitfield properly. (getMissingUnusedIndex): New function(overload). (Range): New class. (getStartIndex): New function. (getEndIndex): New function. (getSparseMissingUnusedIndex): New function. (isBitSetInternal): Return false if the given index is less than 0. * src/HttpInitiateConnectionCommand.h (executeInternal): Pass the reference of segment. * src/FtpNegotiateCommand.h (executeInternal): Pass the reference of segment. * src/FtpNegotiateCommand.cc (recvSize): Initialize bitfield here. * src/FtpTunnelResponseCommand.h (executeInternal): Pass the reference of segment. * src/HttpConnection.cc (createRequest): Rewritten range header processing. * src/DownloadCommand.h (executeInternal): Pass the reference of segment. (prepareForRetry): Removed. (prepareForNextSegment): Added an argument segment. Made it a virtual function. * src/main.cc (main): Set the initial value of PREF_SEGMENT_SIZE to 1MB. * src/SegmentMan.cc (SegmentMan): Added bitfield. Removed splitter. (~SegmentMan): Added bitfield. Removed splitter. (unregisterId): Removed. (getSegment): Rewritten. (updateSegment): Rewritten. (save): Rewritten. (read): Rewritten. (finished): Rewritten. (getDownloadedSize): Removed. (initBitfield): New function. (FindSegmentEntryByIndex): New function object. (FindSegmentEntryByCuid): New function object. (checkoutSegment): New function. (onNullBitfield): New function. (getSegment): New function(overload). (CancelSegment): New function object. (cancelSegment): New function. (completeSegment): New function. (hasSegment): New function. (getDownloadLength): New function. * src/FtpInitiateConnectionCommand.cc (executeInternal): Load .aria2 file after hostname resolution finishes. * src/Segment.h: Rewritten. * src/Segment.cc (operator<<): New function. * src/HttpDownloadCommand.h (prepareForNextSegment): New function. * src/Request.cc (resetUrl): Made segment null. * src/DownloadEngine.cc (~DownloadEngine): Call cleanQueue before deleting segmentMan. * src/HttpProxyRequestCommand.h (executeInternal): Pass the reference of segment. * src/DownloadCommand.cc (executeInternal): Rewritten the code related to Segment. (prepareForRetry): Removed. (prepareForNextSegment): Rewritten. * src/FtpTunnelResponseCommand.h (executeInternal): Pass the reference of segment. To add HTTP 1.1 persistent connection support(experimental) * src/HttpRequestCommand.cc (executeInternal): Disable keep alive if it is disabled by configuration. * src/Request.h (keepAlive): New variable. (isKeepAlive): New function. (setKeepAlive): New function. * src/pref.h (PREF_HTTP_KEEP_ALIVE): New definition. * src/HttpResponseCommand.cc (executeInternal): Check the remote server supports keep alive. * src/HttpConnection.cc (createRequest): Send "Connection: close" only if keep alive is disabled. * src/main.cc (main): Set the initial value(false) of PREF_KEEP_ALIVE to false. To add max download speed limit: * src/pref.h (PREF_MAX_SPEED_LIMIT): New definition. * src/PeerInteractionCommand.cc (executeInternal): Added max download speed limit. Not tested yet. * src/SegmentMan.h (PeerStats): New type definition. (peerStats): New variable. (registerPeerStat): New function. (FindPeerStat): New function object. (getPeerStat): New function. (calculateDownloadSpeed): New function. * src/SpeedCalc.h: New class. * src/SpeedCalc.cc: New class. * src/main.cc (main): Set the initial value of PREF_MAX_SPEED_LIMIT to 0(which means the download speed is not restricted). * src/PeerStat.h: New class. * src/SegmentMan.cc (registerPeerStat): New function. (calculateDownloadSpeed): New function. * src/DownloadCommand.cc (STARTUP_IDLE_TIME): New definition. (DownloadCommand): Register peerStat to segmentMan. Call peerStat-> downloadStart. (~DownloadCommand): Call peerStat->downloadStop. (executeInternal): Added download speed limitter. Rewritten lowest speed limitter. * src/HttpConnection.cc (receiveResponse): Fixed: eohIndex[headerBuf] -> headerBuf[eohIndex]. * src/AbstractCommand.cc (resolveHostname): Throw DlAbortEx if a name resolution failes. Added hostname to the error message. * src/ConsoleDownloadEngine.cc (calculateStatistics): Initialize psize with dlSize. * src/PieceMessage.cc (receivedAction): Do not call peerInteraction->abortPiece here. (onGotWrongPiece): Call peerInteraction->abortPiece here. * src/BitfieldMan.h (clearAllUseBit): New function. (setAllUseBit): New function. * src/BitfieldMan.cc (clearAllBit): Do not clear useBitfield here. (clearAllUseBit): New function. (setAllUseBit): New function. * src/Piece.cc (clearAllBlock): Call bitfield->clearAllUseBit().pull/1/head
parent
1d52ba244e
commit
2fb9b5be97
188
ChangeLog
188
ChangeLog
|
@ -1,3 +1,191 @@
|
||||||
|
2006-09-19 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
|
To rewrite segment download mechanism for HTTP/FTP download.
|
||||||
|
Use BitfieldMan to manage segment download.
|
||||||
|
* src/HttpResponseCommand.h
|
||||||
|
(executeInternal): Pass the reference of segment.
|
||||||
|
* src/AbstractCommand.cc
|
||||||
|
(prepareForRetry): Call segmentMan->cancelSegment here.
|
||||||
|
(onAbort): Call segmentMan->cancelSegment here.
|
||||||
|
* src/HttpDownloadCommand.cc
|
||||||
|
(prepareForNextSegment): New function.
|
||||||
|
* src/DownloadEngineFactory.cc
|
||||||
|
(newConsoleEngine): Removed splitter.
|
||||||
|
(newTorrentConsoleEngine): Removed splitter.
|
||||||
|
* src/Request.h
|
||||||
|
(segment): Renamed from seg.
|
||||||
|
* src/FtpInitiateConnectionCommand.h
|
||||||
|
(executeInternal): Pass the reference of segment.
|
||||||
|
* src/AbstractCommand.h
|
||||||
|
(executeInternal): Pass the reference of segment.
|
||||||
|
* src/pref.h
|
||||||
|
(PREF_SEGMENT_SIZE): New definition.
|
||||||
|
* src/HttpProxyRequestCommand.h
|
||||||
|
(executeInternal): Pass the reference of segment.
|
||||||
|
* src/HttpResponseCommand.cc
|
||||||
|
(checkResponse): Allowed status 206 when a request range starts 0.
|
||||||
|
(handleDefaultEncoding): Rewritten the code related to Segment.
|
||||||
|
(handleOtherEncoding): Rewritten the code related to Segment.
|
||||||
|
* src/SegmentMan.h
|
||||||
|
(SegmentEntry): New class.
|
||||||
|
(SegmentEntries): New type definition.
|
||||||
|
(bitfield): New variable.
|
||||||
|
(usedSegmentEntries): New variable.
|
||||||
|
(onNullBitfield): New function.
|
||||||
|
(checkoutSegment): New function.
|
||||||
|
(segments): Removed.
|
||||||
|
(splitter): Removed.
|
||||||
|
(unregisterId): Removed.
|
||||||
|
(getSegment): New function(overload)
|
||||||
|
(getDownloadedSize): Removed.
|
||||||
|
(cancelSegment): New function.
|
||||||
|
(completeSegment): New function.
|
||||||
|
(initBitfield): New function.
|
||||||
|
(hasSegment): New function.
|
||||||
|
(getDownloadLength): New function.
|
||||||
|
* src/BitfieldMan.h
|
||||||
|
(getStartIndex): New function.
|
||||||
|
(getEndIndex): New function.
|
||||||
|
(getMissingUnusedIndex): New function(overload).
|
||||||
|
(getSparseMissingUnusedIndex): New function.
|
||||||
|
* src/BitfieldMan.cc
|
||||||
|
(getMissingIndexRandomly): Handle the last byte of bitfield properly.
|
||||||
|
(getMissingUnusedIndex): New function(overload).
|
||||||
|
(Range): New class.
|
||||||
|
(getStartIndex): New function.
|
||||||
|
(getEndIndex): New function.
|
||||||
|
(getSparseMissingUnusedIndex): New function.
|
||||||
|
(isBitSetInternal): Return false if the given index is less than 0.
|
||||||
|
* src/HttpInitiateConnectionCommand.h
|
||||||
|
(executeInternal): Pass the reference of segment.
|
||||||
|
* src/FtpNegotiateCommand.h
|
||||||
|
(executeInternal): Pass the reference of segment.
|
||||||
|
* src/FtpNegotiateCommand.cc
|
||||||
|
(recvSize): Initialize bitfield here.
|
||||||
|
* src/FtpTunnelResponseCommand.h
|
||||||
|
(executeInternal): Pass the reference of segment.
|
||||||
|
* src/HttpConnection.cc
|
||||||
|
(createRequest): Rewritten range header processing.
|
||||||
|
* src/DownloadCommand.h
|
||||||
|
(executeInternal): Pass the reference of segment.
|
||||||
|
(prepareForRetry): Removed.
|
||||||
|
(prepareForNextSegment): Added an argument segment. Made it a virtual
|
||||||
|
function.
|
||||||
|
* src/main.cc
|
||||||
|
(main): Set the initial value of PREF_SEGMENT_SIZE to 1MB.
|
||||||
|
* src/SegmentMan.cc
|
||||||
|
(SegmentMan): Added bitfield. Removed splitter.
|
||||||
|
(~SegmentMan): Added bitfield. Removed splitter.
|
||||||
|
(unregisterId): Removed.
|
||||||
|
(getSegment): Rewritten.
|
||||||
|
(updateSegment): Rewritten.
|
||||||
|
(save): Rewritten.
|
||||||
|
(read): Rewritten.
|
||||||
|
(finished): Rewritten.
|
||||||
|
(getDownloadedSize): Removed.
|
||||||
|
(initBitfield): New function.
|
||||||
|
(FindSegmentEntryByIndex): New function object.
|
||||||
|
(FindSegmentEntryByCuid): New function object.
|
||||||
|
(checkoutSegment): New function.
|
||||||
|
(onNullBitfield): New function.
|
||||||
|
(getSegment): New function(overload).
|
||||||
|
(CancelSegment): New function object.
|
||||||
|
(cancelSegment): New function.
|
||||||
|
(completeSegment): New function.
|
||||||
|
(hasSegment): New function.
|
||||||
|
(getDownloadLength): New function.
|
||||||
|
* src/FtpInitiateConnectionCommand.cc
|
||||||
|
(executeInternal): Load .aria2 file after hostname resolution finishes.
|
||||||
|
* src/Segment.h: Rewritten.
|
||||||
|
* src/Segment.cc (operator<<): New function.
|
||||||
|
* src/HttpDownloadCommand.h
|
||||||
|
(prepareForNextSegment): New function.
|
||||||
|
* src/Request.cc
|
||||||
|
(resetUrl): Made segment null.
|
||||||
|
* src/DownloadEngine.cc
|
||||||
|
(~DownloadEngine): Call cleanQueue before deleting segmentMan.
|
||||||
|
* src/HttpProxyRequestCommand.h
|
||||||
|
(executeInternal): Pass the reference of segment.
|
||||||
|
* src/DownloadCommand.cc
|
||||||
|
(executeInternal): Rewritten the code related to Segment.
|
||||||
|
(prepareForRetry): Removed.
|
||||||
|
(prepareForNextSegment): Rewritten.
|
||||||
|
* src/FtpTunnelResponseCommand.h
|
||||||
|
(executeInternal): Pass the reference of segment.
|
||||||
|
|
||||||
|
To add HTTP 1.1 persistent connection support(experimental)
|
||||||
|
* src/HttpRequestCommand.cc
|
||||||
|
(executeInternal): Disable keep alive if it is disabled by
|
||||||
|
configuration.
|
||||||
|
* src/Request.h
|
||||||
|
(keepAlive): New variable.
|
||||||
|
(isKeepAlive): New function.
|
||||||
|
(setKeepAlive): New function.
|
||||||
|
* src/pref.h
|
||||||
|
(PREF_HTTP_KEEP_ALIVE): New definition.
|
||||||
|
* src/HttpResponseCommand.cc
|
||||||
|
(executeInternal): Check the remote server supports keep alive.
|
||||||
|
* src/HttpConnection.cc
|
||||||
|
(createRequest): Send "Connection: close" only if keep alive is
|
||||||
|
disabled.
|
||||||
|
* src/main.cc
|
||||||
|
(main):
|
||||||
|
Set the initial value(false) of PREF_KEEP_ALIVE to false.
|
||||||
|
|
||||||
|
To add max download speed limit:
|
||||||
|
* src/pref.h
|
||||||
|
(PREF_MAX_SPEED_LIMIT): New definition.
|
||||||
|
* src/PeerInteractionCommand.cc
|
||||||
|
(executeInternal): Added max download speed limit. Not tested yet.
|
||||||
|
* src/SegmentMan.h
|
||||||
|
(PeerStats): New type definition.
|
||||||
|
(peerStats): New variable.
|
||||||
|
(registerPeerStat): New function.
|
||||||
|
(FindPeerStat): New function object.
|
||||||
|
(getPeerStat): New function.
|
||||||
|
(calculateDownloadSpeed): New function.
|
||||||
|
* src/SpeedCalc.h: New class.
|
||||||
|
* src/SpeedCalc.cc: New class.
|
||||||
|
* src/main.cc
|
||||||
|
(main):
|
||||||
|
Set the initial value of PREF_MAX_SPEED_LIMIT to 0(which means the
|
||||||
|
download speed is not restricted).
|
||||||
|
* src/PeerStat.h: New class.
|
||||||
|
* src/SegmentMan.cc
|
||||||
|
(registerPeerStat): New function.
|
||||||
|
(calculateDownloadSpeed): New function.
|
||||||
|
* src/DownloadCommand.cc
|
||||||
|
(STARTUP_IDLE_TIME): New definition.
|
||||||
|
(DownloadCommand): Register peerStat to segmentMan. Call peerStat->
|
||||||
|
downloadStart.
|
||||||
|
(~DownloadCommand): Call peerStat->downloadStop.
|
||||||
|
(executeInternal): Added download speed limitter. Rewritten lowest
|
||||||
|
speed limitter.
|
||||||
|
|
||||||
|
* src/HttpConnection.cc
|
||||||
|
(receiveResponse): Fixed: eohIndex[headerBuf] -> headerBuf[eohIndex].
|
||||||
|
|
||||||
|
* src/AbstractCommand.cc
|
||||||
|
(resolveHostname): Throw DlAbortEx if a name resolution failes.
|
||||||
|
Added hostname to the error message.
|
||||||
|
|
||||||
|
* src/ConsoleDownloadEngine.cc
|
||||||
|
(calculateStatistics): Initialize psize with dlSize.
|
||||||
|
|
||||||
|
* src/PieceMessage.cc
|
||||||
|
(receivedAction): Do not call peerInteraction->abortPiece here.
|
||||||
|
(onGotWrongPiece): Call peerInteraction->abortPiece here.
|
||||||
|
|
||||||
|
* src/BitfieldMan.h
|
||||||
|
(clearAllUseBit): New function.
|
||||||
|
(setAllUseBit): New function.
|
||||||
|
* src/BitfieldMan.cc
|
||||||
|
(clearAllBit): Do not clear useBitfield here.
|
||||||
|
(clearAllUseBit): New function.
|
||||||
|
(setAllUseBit): New function.
|
||||||
|
* src/Piece.cc
|
||||||
|
(clearAllBlock): Call bitfield->clearAllUseBit().
|
||||||
|
|
||||||
2006-08-28 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
2006-08-28 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
To make filename URL-decoded:
|
To make filename URL-decoded:
|
||||||
|
|
8
TODO
8
TODO
|
@ -13,5 +13,11 @@
|
||||||
* List available os, version, etc for metalink
|
* List available os, version, etc for metalink
|
||||||
* ipv6(RFC2428 for ftp)
|
* ipv6(RFC2428 for ftp)
|
||||||
* Add silent mode.
|
* Add silent mode.
|
||||||
* Add upload speed limit command-line option.
|
|
||||||
* Save URLs and command-line arguments to .aria2 file.
|
* Save URLs and command-line arguments to .aria2 file.
|
||||||
|
* Add multi-file metalink support.
|
||||||
|
* Add a control port for GUI frontend
|
||||||
|
|
||||||
|
0.8.0
|
||||||
|
|
||||||
|
* Add a statement for the permission to link with OpenSSL.
|
||||||
|
* Add upload speed limit command-line option(not tested for torrent yet).
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.59 for aria2c 0.7.3.
|
# Generated by GNU Autoconf 2.59 for aria2c 0.8.0.
|
||||||
#
|
#
|
||||||
# Report bugs to <tujikawa@rednoah.com>.
|
# Report bugs to <tujikawa@rednoah.com>.
|
||||||
#
|
#
|
||||||
|
@ -269,8 +269,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='aria2c'
|
PACKAGE_NAME='aria2c'
|
||||||
PACKAGE_TARNAME='aria2c'
|
PACKAGE_TARNAME='aria2c'
|
||||||
PACKAGE_VERSION='0.7.3'
|
PACKAGE_VERSION='0.8.0'
|
||||||
PACKAGE_STRING='aria2c 0.7.3'
|
PACKAGE_STRING='aria2c 0.8.0'
|
||||||
PACKAGE_BUGREPORT='tujikawa@rednoah.com'
|
PACKAGE_BUGREPORT='tujikawa@rednoah.com'
|
||||||
|
|
||||||
ac_unique_file="src/Socket.h"
|
ac_unique_file="src/Socket.h"
|
||||||
|
@ -788,7 +788,7 @@ if test "$ac_init_help" = "long"; then
|
||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures aria2c 0.7.3 to adapt to many kinds of systems.
|
\`configure' configures aria2c 0.8.0 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
|
@ -854,7 +854,7 @@ fi
|
||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of aria2c 0.7.3:";;
|
short | recursive ) echo "Configuration of aria2c 0.8.0:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
|
@ -1004,7 +1004,7 @@ fi
|
||||||
test -n "$ac_init_help" && exit 0
|
test -n "$ac_init_help" && exit 0
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
aria2c configure 0.7.3
|
aria2c configure 0.8.0
|
||||||
generated by GNU Autoconf 2.59
|
generated by GNU Autoconf 2.59
|
||||||
|
|
||||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||||
|
@ -1018,7 +1018,7 @@ cat >&5 <<_ACEOF
|
||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by aria2c $as_me 0.7.3, which was
|
It was created by aria2c $as_me 0.8.0, which was
|
||||||
generated by GNU Autoconf 2.59. Invocation command line was
|
generated by GNU Autoconf 2.59. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
|
@ -1661,7 +1661,7 @@ fi
|
||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='aria2c'
|
PACKAGE='aria2c'
|
||||||
VERSION='0.7.3'
|
VERSION='0.8.0'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
@ -12227,7 +12227,7 @@ _ASBOX
|
||||||
} >&5
|
} >&5
|
||||||
cat >&5 <<_CSEOF
|
cat >&5 <<_CSEOF
|
||||||
|
|
||||||
This file was extended by aria2c $as_me 0.7.3, which was
|
This file was extended by aria2c $as_me 0.8.0, which was
|
||||||
generated by GNU Autoconf 2.59. Invocation command line was
|
generated by GNU Autoconf 2.59. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
|
@ -12290,7 +12290,7 @@ _ACEOF
|
||||||
|
|
||||||
cat >>$CONFIG_STATUS <<_ACEOF
|
cat >>$CONFIG_STATUS <<_ACEOF
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
aria2c config.status 0.7.3
|
aria2c config.status 0.8.0
|
||||||
configured by $0, generated by GNU Autoconf 2.59,
|
configured by $0, generated by GNU Autoconf 2.59,
|
||||||
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
|
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
#
|
#
|
||||||
AC_PREREQ(2.59)
|
AC_PREREQ(2.59)
|
||||||
AC_INIT(aria2c, 0.7.3, tujikawa@rednoah.com)
|
AC_INIT(aria2c, 0.8.0, tujikawa@rednoah.com)
|
||||||
AM_INIT_AUTOMAKE()
|
AM_INIT_AUTOMAKE()
|
||||||
AM_PATH_CPPUNIT(1.10.2)
|
AM_PATH_CPPUNIT(1.10.2)
|
||||||
AC_CONFIG_SRCDIR([src/Socket.h])
|
AC_CONFIG_SRCDIR([src/Socket.h])
|
||||||
|
|
|
@ -48,16 +48,18 @@ bool AbstractCommand::execute() {
|
||||||
checkSocketIsWritable && writeCheckTarget->isWritable(0) ||
|
checkSocketIsWritable && writeCheckTarget->isWritable(0) ||
|
||||||
!checkSocketIsReadable && !checkSocketIsWritable) {
|
!checkSocketIsReadable && !checkSocketIsWritable) {
|
||||||
checkPoint.reset();
|
checkPoint.reset();
|
||||||
Segment seg = { 0, 0, 0, false };
|
if(e->segmentMan->finished()) {
|
||||||
|
logger->debug("CUID#%d - finished.", cuid);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Segment segment;
|
||||||
if(e->segmentMan->downloadStarted) {
|
if(e->segmentMan->downloadStarted) {
|
||||||
// get segment information in order to set Range header.
|
if(!e->segmentMan->getSegment(segment, cuid)) {
|
||||||
if(!e->segmentMan->getSegment(seg, cuid)) {
|
|
||||||
// no segment available
|
|
||||||
logger->info(MSG_NO_SEGMENT_AVAILABLE, cuid);
|
logger->info(MSG_NO_SEGMENT_AVAILABLE, cuid);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return executeInternal(seg);
|
return executeInternal(segment);
|
||||||
} else {
|
} else {
|
||||||
if(checkPoint.elapsed(timeout)) {
|
if(checkPoint.elapsed(timeout)) {
|
||||||
throw new DlRetryEx(EX_TIME_OUT);
|
throw new DlRetryEx(EX_TIME_OUT);
|
||||||
|
@ -103,6 +105,7 @@ void AbstractCommand::tryReserved() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AbstractCommand::prepareForRetry(int wait) {
|
bool AbstractCommand::prepareForRetry(int wait) {
|
||||||
|
e->segmentMan->cancelSegment(cuid);
|
||||||
Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, req, e);
|
Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, req, e);
|
||||||
if(wait == 0) {
|
if(wait == 0) {
|
||||||
e->commands.push_back(command);
|
e->commands.push_back(command);
|
||||||
|
@ -115,7 +118,8 @@ bool AbstractCommand::prepareForRetry(int wait) {
|
||||||
|
|
||||||
void AbstractCommand::onAbort(Exception* ex) {
|
void AbstractCommand::onAbort(Exception* ex) {
|
||||||
logger->debug(MSG_UNREGISTER_CUID, cuid);
|
logger->debug(MSG_UNREGISTER_CUID, cuid);
|
||||||
e->segmentMan->unregisterId(cuid);
|
//e->segmentMan->unregisterId(cuid);
|
||||||
|
e->segmentMan->cancelSegment(cuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractCommand::disableReadCheckSocket() {
|
void AbstractCommand::disableReadCheckSocket() {
|
||||||
|
@ -193,7 +197,8 @@ bool AbstractCommand::resolveHostname(const string& hostname,
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
case NameResolver::STATUS_ERROR:
|
case NameResolver::STATUS_ERROR:
|
||||||
throw new DlRetryEx("CUID#%d - Name resolution failed:%s", cuid,
|
throw new DlAbortEx("CUID#%d - Name resolution for %s failed:%s", cuid,
|
||||||
|
hostname.c_str(),
|
||||||
resolver->getError().c_str());
|
resolver->getError().c_str());
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -40,7 +40,7 @@ protected:
|
||||||
void tryReserved();
|
void tryReserved();
|
||||||
virtual bool prepareForRetry(int wait);
|
virtual bool prepareForRetry(int wait);
|
||||||
virtual void onAbort(Exception* ex);
|
virtual void onAbort(Exception* ex);
|
||||||
virtual bool executeInternal(Segment segment) = 0;
|
virtual bool executeInternal(Segment& segment) = 0;
|
||||||
|
|
||||||
void setReadCheckSocket(const SocketHandle& socket);
|
void setReadCheckSocket(const SocketHandle& socket);
|
||||||
void setWriteCheckSocket(const SocketHandle& socket);
|
void setWriteCheckSocket(const SocketHandle& socket);
|
||||||
|
|
|
@ -95,8 +95,20 @@ BitfieldMan::getMissingIndexRandomly(const unsigned char* bitfield,
|
||||||
{
|
{
|
||||||
int byte = (int)(((double)bitfieldLength)*random()/(RAND_MAX+1.0));
|
int byte = (int)(((double)bitfieldLength)*random()/(RAND_MAX+1.0));
|
||||||
|
|
||||||
|
unsigned char lastMask = 0;
|
||||||
|
int lastByteLength = totalLength%(blockLength*8);
|
||||||
|
int lastBlockCount = DIV_FLOOR(lastByteLength, blockLength);
|
||||||
|
for(int i = 0; i < lastBlockCount; i++) {
|
||||||
|
lastMask >>= 1;
|
||||||
|
lastMask |= 0x80;
|
||||||
|
}
|
||||||
for(int i = 0; i < bitfieldLength; i++) {
|
for(int i = 0; i < bitfieldLength; i++) {
|
||||||
unsigned char mask = 0xff;
|
unsigned char mask;
|
||||||
|
if(byte == bitfieldLength-1) {
|
||||||
|
mask = lastMask;
|
||||||
|
} else {
|
||||||
|
mask = 0xff;
|
||||||
|
}
|
||||||
if(bitfield[byte]&mask) {
|
if(bitfield[byte]&mask) {
|
||||||
int index = byte*8+getNthBitIndex(bitfield[byte], 1);
|
int index = byte*8+getNthBitIndex(bitfield[byte], 1);
|
||||||
return index;
|
return index;
|
||||||
|
@ -207,6 +219,82 @@ int BitfieldMan::getMissingIndex() const {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BitfieldMan::getMissingUnusedIndex() const {
|
||||||
|
unsigned char* tempBitfield = new unsigned char[bitfieldLength];
|
||||||
|
memset(tempBitfield, 0xff, bitfieldLength);
|
||||||
|
int index = getMissingUnusedIndex(tempBitfield, bitfieldLength);
|
||||||
|
delete [] tempBitfield;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [startIndex, endIndex)
|
||||||
|
class Range {
|
||||||
|
public:
|
||||||
|
int startIndex;
|
||||||
|
int endIndex;
|
||||||
|
Range(int startIndex = 0, int endIndex = 0):startIndex(startIndex),
|
||||||
|
endIndex(endIndex) {}
|
||||||
|
|
||||||
|
int getSize() const {
|
||||||
|
return endIndex-startIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getMidIndex() const {
|
||||||
|
return (endIndex-startIndex)/2+startIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const Range& range) const {
|
||||||
|
return getSize() < range.getSize();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int BitfieldMan::getStartIndex(int index) const {
|
||||||
|
while(index < blocks &&
|
||||||
|
(isUseBitSet(index) || isBitSet(index))) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if(blocks <= index) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int BitfieldMan::getEndIndex(int index) const {
|
||||||
|
while(index < blocks &&
|
||||||
|
(!isUseBitSet(index) && !isBitSet(index))) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BitfieldMan::getSparseMissingUnusedIndex() const {
|
||||||
|
Range maxRange;
|
||||||
|
int index = 0;
|
||||||
|
int blocks = countBlock();
|
||||||
|
Range currentRange;
|
||||||
|
while(index < blocks) {
|
||||||
|
currentRange.startIndex = getStartIndex(index);
|
||||||
|
if(currentRange.startIndex == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
currentRange.endIndex = getEndIndex(currentRange.startIndex);
|
||||||
|
if(maxRange < currentRange) {
|
||||||
|
maxRange = currentRange;
|
||||||
|
}
|
||||||
|
index = currentRange.endIndex;
|
||||||
|
}
|
||||||
|
if(maxRange.getSize()) {
|
||||||
|
if(maxRange.startIndex == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return maxRange.getMidIndex();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BlockIndexes BitfieldMan::getAllMissingIndexes() const {
|
BlockIndexes BitfieldMan::getAllMissingIndexes() const {
|
||||||
BlockIndexes missingIndexes;
|
BlockIndexes missingIndexes;
|
||||||
for(int i = 0; i < bitfieldLength; i++) {
|
for(int i = 0; i < bitfieldLength; i++) {
|
||||||
|
@ -317,7 +405,7 @@ bool BitfieldMan::isAllBitSet() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BitfieldMan::isBitSetInternal(const unsigned char* bitfield, int index) const {
|
bool BitfieldMan::isBitSetInternal(const unsigned char* bitfield, int index) const {
|
||||||
if(blocks <= index) { return false; }
|
if(index < 0 || blocks <= index) { return false; }
|
||||||
unsigned char mask = 128 >> index%8;
|
unsigned char mask = 128 >> index%8;
|
||||||
return (bitfield[index/8] & mask) != 0;
|
return (bitfield[index/8] & mask) != 0;
|
||||||
}
|
}
|
||||||
|
@ -340,7 +428,6 @@ void BitfieldMan::setBitfield(const unsigned char* bitfield, int bitfieldLength)
|
||||||
|
|
||||||
void BitfieldMan::clearAllBit() {
|
void BitfieldMan::clearAllBit() {
|
||||||
memset(this->bitfield, 0, this->bitfieldLength);
|
memset(this->bitfield, 0, this->bitfieldLength);
|
||||||
memset(this->useBitfield, 0, this->bitfieldLength);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitfieldMan::setAllBit() {
|
void BitfieldMan::setAllBit() {
|
||||||
|
@ -349,6 +436,16 @@ void BitfieldMan::setAllBit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BitfieldMan::clearAllUseBit() {
|
||||||
|
memset(this->useBitfield, 0, this->bitfieldLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitfieldMan::setAllUseBit() {
|
||||||
|
for(int i = 0; i < blocks; i++) {
|
||||||
|
setUseBit(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool BitfieldMan::setFilterBit(int index) {
|
bool BitfieldMan::setFilterBit(int index) {
|
||||||
return setBitInternal(filterBitfield, index, true);
|
return setBitInternal(filterBitfield, index, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,9 @@ private:
|
||||||
bool isBitSetInternal(const unsigned char* bitfield, int index) const;
|
bool isBitSetInternal(const unsigned char* bitfield, int index) const;
|
||||||
bool setBitInternal(unsigned char* bitfield, int index, bool on);
|
bool setBitInternal(unsigned char* bitfield, int index, bool on);
|
||||||
bool setFilterBit(int index);
|
bool setFilterBit(int index);
|
||||||
|
|
||||||
|
int getStartIndex(int index) const;
|
||||||
|
int getEndIndex(int index) const;
|
||||||
public:
|
public:
|
||||||
BitfieldMan(int blockLength, long long int totalLength);
|
BitfieldMan(int blockLength, long long int totalLength);
|
||||||
BitfieldMan(const BitfieldMan& bitfieldMan);
|
BitfieldMan(const BitfieldMan& bitfieldMan);
|
||||||
|
@ -116,6 +119,14 @@ public:
|
||||||
* affected by filter
|
* affected by filter
|
||||||
*/
|
*/
|
||||||
int getMissingUnusedIndex(const unsigned char* bitfield, int len) const;
|
int getMissingUnusedIndex(const unsigned char* bitfield, int len) const;
|
||||||
|
/**
|
||||||
|
* affected by filter
|
||||||
|
*/
|
||||||
|
int getMissingUnusedIndex() const;
|
||||||
|
/**
|
||||||
|
* affected by filter
|
||||||
|
*/
|
||||||
|
int getSparseMissingUnusedIndex() const;
|
||||||
/**
|
/**
|
||||||
* affected by filter
|
* affected by filter
|
||||||
*/
|
*/
|
||||||
|
@ -155,6 +166,9 @@ public:
|
||||||
void clearAllBit();
|
void clearAllBit();
|
||||||
void setAllBit();
|
void setAllBit();
|
||||||
|
|
||||||
|
void clearAllUseBit();
|
||||||
|
void setAllUseBit();
|
||||||
|
|
||||||
void addFilter(long long int offset, long long int length);
|
void addFilter(long long int offset, long long int length);
|
||||||
/**
|
/**
|
||||||
* Clears filter and disables filter
|
* Clears filter and disables filter
|
||||||
|
|
|
@ -51,9 +51,10 @@ void ConsoleDownloadEngine::initStatistics() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleDownloadEngine::calculateStatistics() {
|
void ConsoleDownloadEngine::calculateStatistics() {
|
||||||
long long int dlSize = segmentMan->getDownloadedSize();
|
long long int dlSize = segmentMan->getDownloadLength();
|
||||||
if(!isStartupLengthSet && dlSize > 0) {
|
if(!isStartupLengthSet && dlSize > 0) {
|
||||||
startupLength = dlSize;
|
startupLength = dlSize;
|
||||||
|
psize = dlSize;
|
||||||
isStartupLengthSet = true;
|
isStartupLengthSet = true;
|
||||||
}
|
}
|
||||||
int elapsed = cp.difference();
|
int elapsed = cp.difference();
|
||||||
|
|
|
@ -29,14 +29,30 @@
|
||||||
#include "prefs.h"
|
#include "prefs.h"
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#define STARTUP_IDLE_TIME 10
|
||||||
|
|
||||||
DownloadCommand::DownloadCommand(int cuid, Request* req, DownloadEngine* e,
|
DownloadCommand::DownloadCommand(int cuid, Request* req, DownloadEngine* e,
|
||||||
const SocketHandle& s):
|
const SocketHandle& s):
|
||||||
AbstractCommand(cuid, req, e, s), lastSize(0) {
|
AbstractCommand(cuid, req, e, s), lastSize(0) {
|
||||||
|
PeerStatHandle peerStat = PeerStatHandle(new PeerStat(cuid));
|
||||||
|
peerStat->downloadStart();
|
||||||
|
this->e->segmentMan->registerPeerStat(peerStat);
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadCommand::~DownloadCommand() {}
|
DownloadCommand::~DownloadCommand() {
|
||||||
|
PeerStatHandle peerStat = e->segmentMan->getPeerStat(cuid);
|
||||||
|
assert(peerStat.get());
|
||||||
|
peerStat->downloadStop();
|
||||||
|
}
|
||||||
|
|
||||||
bool DownloadCommand::executeInternal(Segment seg) {
|
bool DownloadCommand::executeInternal(Segment& segment) {
|
||||||
|
int maxSpeedLimit = e->option->getAsInt(PREF_MAX_SPEED_LIMIT);
|
||||||
|
if(maxSpeedLimit > 0 &&
|
||||||
|
maxSpeedLimit < e->segmentMan->calculateDownloadSpeed()) {
|
||||||
|
usleep(1);
|
||||||
|
e->commands.push_back(this);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
TransferEncoding* te = NULL;
|
TransferEncoding* te = NULL;
|
||||||
if(transferEncoding.size()) {
|
if(transferEncoding.size()) {
|
||||||
te = getTransferEncoding(transferEncoding);
|
te = getTransferEncoding(transferEncoding);
|
||||||
|
@ -45,61 +61,78 @@ bool DownloadCommand::executeInternal(Segment seg) {
|
||||||
int bufSize = 4096;
|
int bufSize = 4096;
|
||||||
char buf[bufSize];
|
char buf[bufSize];
|
||||||
socket->readData(buf, bufSize);
|
socket->readData(buf, bufSize);
|
||||||
|
PeerStatHandle peerStat = e->segmentMan->getPeerStat(cuid);
|
||||||
|
assert(peerStat.get());
|
||||||
if(te != NULL) {
|
if(te != NULL) {
|
||||||
int infbufSize = 4096;
|
int infbufSize = 4096;
|
||||||
char infbuf[infbufSize];
|
char infbuf[infbufSize];
|
||||||
te->inflate(infbuf, infbufSize, buf, bufSize);
|
te->inflate(infbuf, infbufSize, buf, bufSize);
|
||||||
e->segmentMan->diskWriter->writeData(infbuf, infbufSize, seg.sp+seg.ds);
|
e->segmentMan->diskWriter->writeData(infbuf, infbufSize,
|
||||||
seg.ds += infbufSize;
|
segment.getPosition()+segment.writtenLength);
|
||||||
|
segment.writtenLength += infbufSize;
|
||||||
|
peerStat->updateDownloadLength(infbufSize);
|
||||||
} else {
|
} else {
|
||||||
e->segmentMan->diskWriter->writeData(buf, bufSize, seg.sp+seg.ds);
|
e->segmentMan->diskWriter->writeData(buf, bufSize,
|
||||||
seg.ds += bufSize;
|
segment.getPosition()+segment.writtenLength);
|
||||||
|
segment.writtenLength += bufSize;
|
||||||
|
peerStat->updateDownloadLength(bufSize);
|
||||||
}
|
}
|
||||||
// calculate downloading speed
|
// calculate downloading speed
|
||||||
int diff = sw.difference();
|
if(/*sw.elapsed(1) >= 1 && */peerStat->getDownloadStartTime().elapsed(STARTUP_IDLE_TIME)) {
|
||||||
if(diff >= 1) {
|
|
||||||
seg.speed = (int)((seg.ds-lastSize)/(diff*1.0));
|
|
||||||
sw.reset();
|
|
||||||
lastSize = seg.ds;
|
|
||||||
int lowestLimit = e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT);
|
int lowestLimit = e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT);
|
||||||
if(lowestLimit > 0 && seg.speed <= lowestLimit) {
|
int nowSpeed = peerStat->calculateDownloadSpeed();
|
||||||
|
if(lowestLimit > 0 && nowSpeed <= lowestLimit) {
|
||||||
throw new DlAbortEx("CUID#%d - Too slow Downloading speed: %d <= %d(B/s)",
|
throw new DlAbortEx("CUID#%d - Too slow Downloading speed: %d <= %d(B/s)",
|
||||||
cuid,
|
cuid,
|
||||||
seg.speed,
|
nowSpeed,
|
||||||
lowestLimit);
|
lowestLimit);
|
||||||
}
|
}
|
||||||
|
//sw.reset();
|
||||||
}
|
}
|
||||||
if(e->segmentMan->totalSize != 0 && bufSize == 0) {
|
if(e->segmentMan->totalSize != 0 && bufSize == 0) {
|
||||||
throw new DlRetryEx(EX_GOT_EOF);
|
throw new DlRetryEx(EX_GOT_EOF);
|
||||||
}
|
}
|
||||||
if(te != NULL && te->finished()
|
if(te != NULL && te->finished()
|
||||||
|| te == NULL && seg.ds >= seg.ep-seg.sp+1
|
|| te == NULL && segment.complete()
|
||||||
|| bufSize == 0) {
|
|| bufSize == 0) {
|
||||||
if(te != NULL) te->end();
|
if(te != NULL) te->end();
|
||||||
logger->info(MSG_DOWNLOAD_COMPLETED, cuid);
|
logger->info(MSG_DOWNLOAD_COMPLETED, cuid);
|
||||||
seg.ds = seg.ep-seg.sp+1;
|
e->segmentMan->completeSegment(cuid, segment);
|
||||||
seg.finish = true;
|
|
||||||
e->segmentMan->updateSegment(seg);
|
|
||||||
// this unit is going to download another segment.
|
// this unit is going to download another segment.
|
||||||
return prepareForNextSegment();
|
return prepareForNextSegment(segment);
|
||||||
} else {
|
} else {
|
||||||
e->segmentMan->updateSegment(seg);
|
e->segmentMan->updateSegment(cuid, segment);
|
||||||
e->commands.push_back(this);
|
e->commands.push_back(this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DownloadCommand::prepareForRetry(int wait) {
|
bool DownloadCommand::prepareForNextSegment(const Segment& currentSegment) {
|
||||||
//req->resetUrl();
|
if(e->segmentMan->finished()) {
|
||||||
return AbstractCommand::prepareForRetry(wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DownloadCommand::prepareForNextSegment() {
|
|
||||||
req->resetUrl();
|
|
||||||
if(!e->segmentMan->finished()) {
|
|
||||||
return AbstractCommand::prepareForRetry(0);
|
|
||||||
} else {
|
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
// Merge segment with next segment, if segment.index+1 == nextSegment.index
|
||||||
|
Segment tempSegment = currentSegment;
|
||||||
|
while(1) {
|
||||||
|
Segment nextSegment;
|
||||||
|
if(e->segmentMan->getSegment(nextSegment, cuid, tempSegment.index+1)) {
|
||||||
|
if(nextSegment.writtenLength > 0) {
|
||||||
|
return prepareForRetry(0);
|
||||||
|
}
|
||||||
|
nextSegment.writtenLength = tempSegment.writtenLength-tempSegment.length;
|
||||||
|
if(nextSegment.complete()) {
|
||||||
|
e->segmentMan->completeSegment(cuid, nextSegment);
|
||||||
|
tempSegment = nextSegment;
|
||||||
|
} else {
|
||||||
|
e->segmentMan->updateSegment(cuid, nextSegment);
|
||||||
|
e->commands.push_back(this);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prepareForRetry(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,10 +33,9 @@ private:
|
||||||
Time sw;
|
Time sw;
|
||||||
long long int lastSize;
|
long long int lastSize;
|
||||||
protected:
|
protected:
|
||||||
bool executeInternal(Segment segment);
|
bool executeInternal(Segment& segment);
|
||||||
|
|
||||||
bool prepareForRetry(int wait);
|
virtual bool prepareForNextSegment(const Segment& currentSegment);
|
||||||
bool prepareForNextSegment();
|
|
||||||
public:
|
public:
|
||||||
DownloadCommand(int cuid, Request* req, DownloadEngine* e,
|
DownloadCommand(int cuid, Request* req, DownloadEngine* e,
|
||||||
const SocketHandle& s);
|
const SocketHandle& s);
|
||||||
|
|
|
@ -37,8 +37,8 @@ DownloadEngine::DownloadEngine():noWait(false), segmentMan(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadEngine::~DownloadEngine() {
|
DownloadEngine::~DownloadEngine() {
|
||||||
delete segmentMan;
|
|
||||||
cleanQueue();
|
cleanQueue();
|
||||||
|
delete segmentMan;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadEngine::cleanQueue() {
|
void DownloadEngine::cleanQueue() {
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include "DownloadEngineFactory.h"
|
#include "DownloadEngineFactory.h"
|
||||||
#include "prefs.h"
|
#include "prefs.h"
|
||||||
#include "DefaultDiskWriter.h"
|
#include "DefaultDiskWriter.h"
|
||||||
#include "SplitSlowestSegmentSplitter.h"
|
|
||||||
#include "InitiateConnectionCommandFactory.h"
|
#include "InitiateConnectionCommandFactory.h"
|
||||||
#include "ByteArrayDiskWriter.h"
|
#include "ByteArrayDiskWriter.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
@ -51,8 +50,6 @@ DownloadEngineFactory::newConsoleEngine(const Option* op,
|
||||||
e->segmentMan->dir = op->get(PREF_DIR);
|
e->segmentMan->dir = op->get(PREF_DIR);
|
||||||
e->segmentMan->ufilename = op->get(PREF_OUT);
|
e->segmentMan->ufilename = op->get(PREF_OUT);
|
||||||
e->segmentMan->option = op;
|
e->segmentMan->option = op;
|
||||||
e->segmentMan->splitter = new SplitSlowestSegmentSplitter();
|
|
||||||
e->segmentMan->splitter->setMinSegmentSize(op->getAsLLInt(PREF_MIN_SEGMENT_SIZE));
|
|
||||||
e->segmentMan->reserved = reserved;
|
e->segmentMan->reserved = reserved;
|
||||||
|
|
||||||
int cuidCounter = 1;
|
int cuidCounter = 1;
|
||||||
|
@ -79,8 +76,6 @@ DownloadEngineFactory::newTorrentConsoleEngine(const Option* op,
|
||||||
te->segmentMan = new SegmentMan();
|
te->segmentMan = new SegmentMan();
|
||||||
te->segmentMan->diskWriter = byteArrayDiskWriter;
|
te->segmentMan->diskWriter = byteArrayDiskWriter;
|
||||||
te->segmentMan->option = op;
|
te->segmentMan->option = op;
|
||||||
te->segmentMan->splitter = new SplitSlowestSegmentSplitter();
|
|
||||||
te->segmentMan->splitter->setMinSegmentSize(op->getAsLLInt(PREF_MIN_SEGMENT_SIZE));
|
|
||||||
te->torrentMan = new TorrentMan();
|
te->torrentMan = new TorrentMan();
|
||||||
te->torrentMan->setStoreDir(op->get(PREF_DIR));
|
te->torrentMan->setStoreDir(op->get(PREF_DIR));
|
||||||
te->torrentMan->option = op;
|
te->torrentMan->option = op;
|
||||||
|
|
|
@ -97,7 +97,7 @@ SocketHandle FtpConnection::sendPort() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FtpConnection::sendRest(const Segment& segment) const {
|
void FtpConnection::sendRest(const Segment& segment) const {
|
||||||
string request = "REST "+Util::llitos(segment.sp+segment.ds)+"\r\n";
|
string request = "REST "+Util::llitos(segment.getPosition()+segment.writtenLength)+"\r\n";
|
||||||
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
|
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
|
||||||
socket->writeData(request);
|
socket->writeData(request);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,8 @@ FtpDownloadCommand::FtpDownloadCommand(int cuid, Request* req,
|
||||||
DownloadEngine* e,
|
DownloadEngine* e,
|
||||||
const SocketHandle& dataSocket,
|
const SocketHandle& dataSocket,
|
||||||
const SocketHandle& ctrlSocket)
|
const SocketHandle& ctrlSocket)
|
||||||
:DownloadCommand(cuid, req, e, dataSocket), ctrlSocket(ctrlSocket) {}
|
:DownloadCommand(cuid, req, e, dataSocket),
|
||||||
|
ctrlSocket(ctrlSocket) {}
|
||||||
|
|
||||||
FtpDownloadCommand::~FtpDownloadCommand() {}
|
FtpDownloadCommand::~FtpDownloadCommand() {}
|
||||||
|
|
||||||
|
|
|
@ -43,18 +43,7 @@ FtpInitiateConnectionCommand::~FtpInitiateConnectionCommand() {
|
||||||
#endif // ENABLE_ASYNC_DNS
|
#endif // ENABLE_ASYNC_DNS
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FtpInitiateConnectionCommand::executeInternal(Segment segment) {
|
bool FtpInitiateConnectionCommand::executeInternal(Segment& segment) {
|
||||||
if(!e->segmentMan->downloadStarted) {
|
|
||||||
e->segmentMan->filename = Util::urldecode(req->getFile());
|
|
||||||
bool segFileExists = e->segmentMan->segmentFileExists();
|
|
||||||
if(segFileExists) {
|
|
||||||
e->segmentMan->load();
|
|
||||||
e->segmentMan->diskWriter->openExistingFile(e->segmentMan->getFilePath());
|
|
||||||
e->segmentMan->downloadStarted = true;
|
|
||||||
} else {
|
|
||||||
e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
string hostname;
|
string hostname;
|
||||||
if(useHttpProxy()) {
|
if(useHttpProxy()) {
|
||||||
hostname = e->option->get(PREF_HTTP_PROXY_HOST);
|
hostname = e->option->get(PREF_HTTP_PROXY_HOST);
|
||||||
|
@ -71,6 +60,17 @@ bool FtpInitiateConnectionCommand::executeInternal(Segment segment) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // ENABLE_ASYNC_DNS
|
#endif // ENABLE_ASYNC_DNS
|
||||||
|
if(!e->segmentMan->downloadStarted) {
|
||||||
|
e->segmentMan->filename = Util::urldecode(req->getFile());
|
||||||
|
bool segFileExists = e->segmentMan->segmentFileExists();
|
||||||
|
if(segFileExists) {
|
||||||
|
e->segmentMan->load();
|
||||||
|
e->segmentMan->diskWriter->openExistingFile(e->segmentMan->getFilePath());
|
||||||
|
e->segmentMan->downloadStarted = true;
|
||||||
|
} else {
|
||||||
|
e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
Command* command;
|
Command* command;
|
||||||
if(useHttpProxy()) {
|
if(useHttpProxy()) {
|
||||||
logger->info(MSG_CONNECTING_TO_SERVER, cuid,
|
logger->info(MSG_CONNECTING_TO_SERVER, cuid,
|
||||||
|
|
|
@ -33,7 +33,7 @@ private:
|
||||||
bool useHttpProxyGet() const;
|
bool useHttpProxyGet() const;
|
||||||
bool useHttpProxyConnect() const;
|
bool useHttpProxyConnect() const;
|
||||||
protected:
|
protected:
|
||||||
bool executeInternal(Segment segment);
|
bool executeInternal(Segment& segment);
|
||||||
public:
|
public:
|
||||||
FtpInitiateConnectionCommand(int cuid, Request* req, DownloadEngine* e);
|
FtpInitiateConnectionCommand(int cuid, Request* req, DownloadEngine* e);
|
||||||
~FtpInitiateConnectionCommand();
|
~FtpInitiateConnectionCommand();
|
||||||
|
|
|
@ -40,7 +40,7 @@ FtpNegotiationCommand::~FtpNegotiationCommand() {
|
||||||
delete ftp;
|
delete ftp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FtpNegotiationCommand::executeInternal(Segment segment) {
|
bool FtpNegotiationCommand::executeInternal(Segment& segment) {
|
||||||
while(processSequence(segment));
|
while(processSequence(segment));
|
||||||
if(sequence == SEQ_RETRY) {
|
if(sequence == SEQ_RETRY) {
|
||||||
return prepareForRetry(0);
|
return prepareForRetry(0);
|
||||||
|
@ -170,6 +170,8 @@ bool FtpNegotiationCommand::recvSize() {
|
||||||
if(!e->segmentMan->downloadStarted) {
|
if(!e->segmentMan->downloadStarted) {
|
||||||
e->segmentMan->downloadStarted = true;
|
e->segmentMan->downloadStarted = true;
|
||||||
e->segmentMan->totalSize = size;
|
e->segmentMan->totalSize = size;
|
||||||
|
e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE),
|
||||||
|
e->segmentMan->totalSize);
|
||||||
} else if(e->segmentMan->totalSize != size) {
|
} else if(e->segmentMan->totalSize != size) {
|
||||||
throw new DlAbortEx(EX_SIZE_MISMATCH, e->segmentMan->totalSize, size);
|
throw new DlAbortEx(EX_SIZE_MISMATCH, e->segmentMan->totalSize, size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ private:
|
||||||
int sequence;
|
int sequence;
|
||||||
FtpConnection* ftp;
|
FtpConnection* ftp;
|
||||||
protected:
|
protected:
|
||||||
bool executeInternal(Segment segment);
|
bool executeInternal(Segment& segment);
|
||||||
public:
|
public:
|
||||||
FtpNegotiationCommand(int cuid, Request* req, DownloadEngine* e,
|
FtpNegotiationCommand(int cuid, Request* req, DownloadEngine* e,
|
||||||
const SocketHandle& s);
|
const SocketHandle& s);
|
||||||
|
|
|
@ -33,7 +33,7 @@ FtpTunnelRequestCommand::FtpTunnelRequestCommand(int cuid, Request* req,
|
||||||
|
|
||||||
FtpTunnelRequestCommand::~FtpTunnelRequestCommand() {}
|
FtpTunnelRequestCommand::~FtpTunnelRequestCommand() {}
|
||||||
|
|
||||||
bool FtpTunnelRequestCommand::executeInternal(Segment segment) {
|
bool FtpTunnelRequestCommand::executeInternal(Segment& segment) {
|
||||||
socket->setBlockingMode();
|
socket->setBlockingMode();
|
||||||
HttpConnection httpConnection(cuid, socket, req, e->option);
|
HttpConnection httpConnection(cuid, socket, req, e->option);
|
||||||
httpConnection.sendProxyRequest();
|
httpConnection.sendProxyRequest();
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
class FtpTunnelRequestCommand : public AbstractCommand {
|
class FtpTunnelRequestCommand : public AbstractCommand {
|
||||||
protected:
|
protected:
|
||||||
bool executeInternal(Segment segment);
|
bool executeInternal(Segment& segment);
|
||||||
public:
|
public:
|
||||||
FtpTunnelRequestCommand(int cuid, Request* req, DownloadEngine* e,
|
FtpTunnelRequestCommand(int cuid, Request* req, DownloadEngine* e,
|
||||||
const SocketHandle& s);
|
const SocketHandle& s);
|
||||||
|
|
|
@ -35,7 +35,7 @@ FtpTunnelResponseCommand::~FtpTunnelResponseCommand() {
|
||||||
delete http;
|
delete http;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FtpTunnelResponseCommand::executeInternal(Segment segment) {
|
bool FtpTunnelResponseCommand::executeInternal(Segment& segment) {
|
||||||
HttpHeader headers;
|
HttpHeader headers;
|
||||||
int status = http->receiveResponse(headers);
|
int status = http->receiveResponse(headers);
|
||||||
if(status == 0) {
|
if(status == 0) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ class FtpTunnelResponseCommand : public AbstractCommand {
|
||||||
private:
|
private:
|
||||||
HttpConnection* http;
|
HttpConnection* http;
|
||||||
protected:
|
protected:
|
||||||
bool executeInternal(Segment segment);
|
bool executeInternal(Segment& segment);
|
||||||
public:
|
public:
|
||||||
FtpTunnelResponseCommand(int cuid, Request* req, DownloadEngine* e,
|
FtpTunnelResponseCommand(int cuid, Request* req, DownloadEngine* e,
|
||||||
const SocketHandle& s);
|
const SocketHandle& s);
|
||||||
|
|
|
@ -71,14 +71,23 @@ string HttpConnection::createRequest(const Segment& segment) const {
|
||||||
((req->getDir() == "/" ? "/" : req->getDir()+"/")+req->getFile()))+
|
((req->getDir() == "/" ? "/" : req->getDir()+"/")+req->getFile()))+
|
||||||
string(" HTTP/1.1\r\n")+
|
string(" HTTP/1.1\r\n")+
|
||||||
"User-Agent: "+USER_AGENT+"\r\n"+
|
"User-Agent: "+USER_AGENT+"\r\n"+
|
||||||
"Connection: close\r\n"+
|
// use persistent connection
|
||||||
|
//"Connection: close\r\n"+
|
||||||
"Accept: */*\r\n"+ /* */
|
"Accept: */*\r\n"+ /* */
|
||||||
"Host: "+getHost(req->getHost(), req->getPort())+"\r\n"+
|
"Host: "+getHost(req->getHost(), req->getPort())+"\r\n"+
|
||||||
"Pragma: no-cache\r\n"+
|
"Pragma: no-cache\r\n"+
|
||||||
"Cache-Control: no-cache\r\n";
|
"Cache-Control: no-cache\r\n";
|
||||||
if(segment.sp+segment.ds > 0) {
|
if(!req->isKeepAlive()) {
|
||||||
|
request += "Connection: close\r\n";
|
||||||
|
}
|
||||||
|
if(segment.length > 0) {
|
||||||
request += "Range: bytes="+
|
request += "Range: bytes="+
|
||||||
Util::llitos(segment.sp+segment.ds)+"-"+Util::llitos(segment.ep)+"\r\n";
|
Util::llitos(segment.getPosition()+segment.writtenLength);
|
||||||
|
request += "-";
|
||||||
|
if(req->isKeepAlive()) {
|
||||||
|
request += Util::llitos(segment.getPosition()+segment.length-1);
|
||||||
|
}
|
||||||
|
request += "\r\n";
|
||||||
}
|
}
|
||||||
if(useProxy() && useProxyAuth() && useProxyGet()) {
|
if(useProxy() && useProxyAuth() && useProxyGet()) {
|
||||||
request += "Proxy-Connection: close\r\n";
|
request += "Proxy-Connection: close\r\n";
|
||||||
|
@ -144,7 +153,7 @@ int HttpConnection::receiveResponse(HttpHeader& headers) {
|
||||||
socket->readData(headerBuf+headerBufLength, size);
|
socket->readData(headerBuf+headerBufLength, size);
|
||||||
headerBufLength += size;
|
headerBufLength += size;
|
||||||
} else {
|
} else {
|
||||||
if(eohIndex[headerBuf] == '\n') {
|
if(headerBuf[eohIndex] == '\n') {
|
||||||
// for crapping non-standard HTTP server
|
// for crapping non-standard HTTP server
|
||||||
delimiterSwitch = 1;
|
delimiterSwitch = 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -20,14 +20,15 @@
|
||||||
*/
|
*/
|
||||||
/* copyright --> */
|
/* copyright --> */
|
||||||
#include "HttpDownloadCommand.h"
|
#include "HttpDownloadCommand.h"
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include "DlRetryEx.h"
|
#include "DlRetryEx.h"
|
||||||
#include "HttpRequestCommand.h"
|
#include "HttpRequestCommand.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "ChunkedEncoding.h"
|
#include "ChunkedEncoding.h"
|
||||||
|
#include "message.h"
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -49,3 +50,17 @@ HttpDownloadCommand::~HttpDownloadCommand() {
|
||||||
TransferEncoding* HttpDownloadCommand::getTransferEncoding(const string& name) {
|
TransferEncoding* HttpDownloadCommand::getTransferEncoding(const string& name) {
|
||||||
return transferEncodings[name];
|
return transferEncodings[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HttpDownloadCommand::prepareForNextSegment(const Segment& currentSegment) {
|
||||||
|
if(e->segmentMan->finished()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if(req->isKeepAlive()) {
|
||||||
|
Command* command = new HttpRequestCommand(cuid, req, e, socket);
|
||||||
|
e->commands.push_back(command);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return DownloadCommand::prepareForNextSegment(currentSegment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@ using namespace std;
|
||||||
class HttpDownloadCommand:public DownloadCommand {
|
class HttpDownloadCommand:public DownloadCommand {
|
||||||
private:
|
private:
|
||||||
map<string, TransferEncoding*> transferEncodings;
|
map<string, TransferEncoding*> transferEncodings;
|
||||||
|
protected:
|
||||||
|
virtual bool prepareForNextSegment(const Segment& currentSegment);
|
||||||
public:
|
public:
|
||||||
HttpDownloadCommand(int cuid, Request* req, DownloadEngine* e,
|
HttpDownloadCommand(int cuid, Request* req, DownloadEngine* e,
|
||||||
const SocketHandle& s);
|
const SocketHandle& s);
|
||||||
|
|
|
@ -43,7 +43,7 @@ HttpInitiateConnectionCommand::~HttpInitiateConnectionCommand() {
|
||||||
#endif // ENABLE_ASYNC_DNS
|
#endif // ENABLE_ASYNC_DNS
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HttpInitiateConnectionCommand::executeInternal(Segment segment) {
|
bool HttpInitiateConnectionCommand::executeInternal(Segment& segment) {
|
||||||
string hostname;
|
string hostname;
|
||||||
if(useProxy()) {
|
if(useProxy()) {
|
||||||
hostname = e->option->get(PREF_HTTP_PROXY_HOST);
|
hostname = e->option->get(PREF_HTTP_PROXY_HOST);
|
||||||
|
|
|
@ -41,7 +41,7 @@ protected:
|
||||||
* Whether or not the connection is established successfully is
|
* Whether or not the connection is established successfully is
|
||||||
* evaluated by RequestCommand.
|
* evaluated by RequestCommand.
|
||||||
*/
|
*/
|
||||||
bool executeInternal(Segment segment);
|
bool executeInternal(Segment& segment);
|
||||||
public:
|
public:
|
||||||
HttpInitiateConnectionCommand(int cuid, Request* req, DownloadEngine* e);
|
HttpInitiateConnectionCommand(int cuid, Request* req, DownloadEngine* e);
|
||||||
~HttpInitiateConnectionCommand();
|
~HttpInitiateConnectionCommand();
|
||||||
|
|
|
@ -33,7 +33,7 @@ HttpProxyRequestCommand::HttpProxyRequestCommand(int cuid, Request* req,
|
||||||
|
|
||||||
HttpProxyRequestCommand::~HttpProxyRequestCommand() {}
|
HttpProxyRequestCommand::~HttpProxyRequestCommand() {}
|
||||||
|
|
||||||
bool HttpProxyRequestCommand::executeInternal(Segment segment) {
|
bool HttpProxyRequestCommand::executeInternal(Segment& segment) {
|
||||||
socket->setBlockingMode();
|
socket->setBlockingMode();
|
||||||
HttpConnection httpConnection(cuid, socket, req, e->option);
|
HttpConnection httpConnection(cuid, socket, req, e->option);
|
||||||
httpConnection.sendProxyRequest();
|
httpConnection.sendProxyRequest();
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
class HttpProxyRequestCommand : public AbstractCommand {
|
class HttpProxyRequestCommand : public AbstractCommand {
|
||||||
protected:
|
protected:
|
||||||
bool executeInternal(Segment segment);
|
bool executeInternal(Segment& segment);
|
||||||
public:
|
public:
|
||||||
HttpProxyRequestCommand(int cuid, Request* req, DownloadEngine* e,
|
HttpProxyRequestCommand(int cuid, Request* req, DownloadEngine* e,
|
||||||
const SocketHandle& s);
|
const SocketHandle& s);
|
||||||
|
|
|
@ -35,7 +35,7 @@ HttpProxyResponseCommand::~HttpProxyResponseCommand() {
|
||||||
delete http;
|
delete http;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HttpProxyResponseCommand::executeInternal(Segment segment) {
|
bool HttpProxyResponseCommand::executeInternal(Segment& segment) {
|
||||||
HttpHeader headers;
|
HttpHeader headers;
|
||||||
int status = http->receiveResponse(headers);
|
int status = http->receiveResponse(headers);
|
||||||
if(status == 0) {
|
if(status == 0) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ class HttpProxyResponseCommand : public AbstractCommand {
|
||||||
private:
|
private:
|
||||||
HttpConnection* http;
|
HttpConnection* http;
|
||||||
protected:
|
protected:
|
||||||
bool executeInternal(Segment segment);
|
bool executeInternal(Segment& segment);
|
||||||
public:
|
public:
|
||||||
HttpProxyResponseCommand(int cuid, Request* req, DownloadEngine* e,
|
HttpProxyResponseCommand(int cuid, Request* req, DownloadEngine* e,
|
||||||
const SocketHandle& s);
|
const SocketHandle& s);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "HttpRequestCommand.h"
|
#include "HttpRequestCommand.h"
|
||||||
#include "HttpResponseCommand.h"
|
#include "HttpResponseCommand.h"
|
||||||
#include "HttpConnection.h"
|
#include "HttpConnection.h"
|
||||||
|
#include "prefs.h"
|
||||||
|
|
||||||
HttpRequestCommand::HttpRequestCommand(int cuid, Request* req,
|
HttpRequestCommand::HttpRequestCommand(int cuid, Request* req,
|
||||||
DownloadEngine* e,
|
DownloadEngine* e,
|
||||||
|
@ -33,15 +34,17 @@ HttpRequestCommand::HttpRequestCommand(int cuid, Request* req,
|
||||||
|
|
||||||
HttpRequestCommand::~HttpRequestCommand() {}
|
HttpRequestCommand::~HttpRequestCommand() {}
|
||||||
|
|
||||||
bool HttpRequestCommand::executeInternal(Segment seg) {
|
bool HttpRequestCommand::executeInternal(Segment& segment) {
|
||||||
socket->setBlockingMode();
|
socket->setBlockingMode();
|
||||||
if(req->getProtocol() == "https") {
|
if(req->getProtocol() == "https") {
|
||||||
socket->initiateSecureConnection();
|
socket->initiateSecureConnection();
|
||||||
}
|
}
|
||||||
|
if(!e->option->getAsBool(PREF_HTTP_KEEP_ALIVE)) {
|
||||||
|
req->setKeepAlive(false);
|
||||||
|
}
|
||||||
HttpConnection http(cuid, socket, req, e->option);
|
HttpConnection http(cuid, socket, req, e->option);
|
||||||
// set seg to request in order to remember the request range
|
req->segment = segment;
|
||||||
req->seg = seg;
|
http.sendRequest(segment);
|
||||||
http.sendRequest(seg);
|
|
||||||
|
|
||||||
Command* command = getNextCommand();
|
Command* command = getNextCommand();
|
||||||
e->commands.push_back(command);
|
e->commands.push_back(command);
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
class HttpRequestCommand:public AbstractCommand {
|
class HttpRequestCommand:public AbstractCommand {
|
||||||
protected:
|
protected:
|
||||||
bool executeInternal(Segment segment);
|
bool executeInternal(Segment& segment);
|
||||||
Command* getNextCommand() const;
|
Command* getNextCommand() const;
|
||||||
public:
|
public:
|
||||||
HttpRequestCommand(int cuid, Request* req, DownloadEngine* e,
|
HttpRequestCommand(int cuid, Request* req, DownloadEngine* e,
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "HttpInitiateConnectionCommand.h"
|
#include "HttpInitiateConnectionCommand.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
#include "prefs.h"
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -40,8 +41,8 @@ HttpResponseCommand::~HttpResponseCommand() {
|
||||||
delete http;
|
delete http;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HttpResponseCommand::executeInternal(Segment seg) {
|
bool HttpResponseCommand::executeInternal(Segment& segment) {
|
||||||
if(req->seg.sp != seg.sp) {
|
if(req->segment != segment) {
|
||||||
logger->info(MSG_SEGMENT_CHANGED, cuid);
|
logger->info(MSG_SEGMENT_CHANGED, cuid);
|
||||||
return prepareForRetry(0);
|
return prepareForRetry(0);
|
||||||
}
|
}
|
||||||
|
@ -53,8 +54,12 @@ bool HttpResponseCommand::executeInternal(Segment seg) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// check HTTP status number
|
// check HTTP status number
|
||||||
checkResponse(status, seg);
|
checkResponse(status, segment);
|
||||||
retrieveCookie(headers);
|
retrieveCookie(headers);
|
||||||
|
// check whether the server supports persistent connections.
|
||||||
|
if(Util::toLower(headers.getFirst("Connection")).find("close") != string::npos) {
|
||||||
|
req->setKeepAlive(false);
|
||||||
|
}
|
||||||
// check whether Location header exists. If it does, update request object
|
// check whether Location header exists. If it does, update request object
|
||||||
// with redirected URL.
|
// with redirected URL.
|
||||||
// then establish a connection to the new host and port
|
// then establish a connection to the new host and port
|
||||||
|
@ -64,7 +69,8 @@ bool HttpResponseCommand::executeInternal(Segment seg) {
|
||||||
if(!e->segmentMan->downloadStarted) {
|
if(!e->segmentMan->downloadStarted) {
|
||||||
string transferEncoding;
|
string transferEncoding;
|
||||||
if(headers.defined("Transfer-Encoding")) {
|
if(headers.defined("Transfer-Encoding")) {
|
||||||
return handleOtherEncoding(headers.getFirst("Transfer-Encoding"), headers);
|
return handleOtherEncoding(headers.getFirst("Transfer-Encoding"),
|
||||||
|
headers);
|
||||||
} else {
|
} else {
|
||||||
return handleDefaultEncoding(headers);
|
return handleDefaultEncoding(headers);
|
||||||
}
|
}
|
||||||
|
@ -82,8 +88,8 @@ void HttpResponseCommand::checkResponse(int status, const Segment& segment) {
|
||||||
throw new DlAbortEx(EX_AUTH_FAILED);
|
throw new DlAbortEx(EX_AUTH_FAILED);
|
||||||
}
|
}
|
||||||
if(!(300 <= status && status < 400 ||
|
if(!(300 <= status && status < 400 ||
|
||||||
(segment.sp+segment.ds == 0 && status == 200)
|
(segment.getPosition()+segment.writtenLength == 0 && (status == 200 || status == 206)) ||
|
||||||
|| (segment.sp+segment.ds > 0 && status == 206))) {
|
(segment.getPosition()+segment.writtenLength > 0 && status == 206))) {
|
||||||
throw new DlRetryEx(EX_BAD_STATUS, status);
|
throw new DlRetryEx(EX_BAD_STATUS, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,6 +118,8 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) {
|
||||||
if(req->isTorrent) {
|
if(req->isTorrent) {
|
||||||
long long int size = headers.getFirstAsLLInt("Content-Length");
|
long long int size = headers.getFirstAsLLInt("Content-Length");
|
||||||
e->segmentMan->totalSize = size;
|
e->segmentMan->totalSize = size;
|
||||||
|
e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE),
|
||||||
|
e->segmentMan->totalSize);
|
||||||
e->segmentMan->isSplittable = false;
|
e->segmentMan->isSplittable = false;
|
||||||
e->segmentMan->downloadStarted = true;
|
e->segmentMan->downloadStarted = true;
|
||||||
e->segmentMan->diskWriter->initAndOpenFile("/tmp/aria2"+Util::itos(getpid()));
|
e->segmentMan->diskWriter->initAndOpenFile("/tmp/aria2"+Util::itos(getpid()));
|
||||||
|
@ -134,11 +142,10 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) {
|
||||||
return prepareForRetry(0);
|
return prepareForRetry(0);
|
||||||
} else {
|
} else {
|
||||||
e->segmentMan->totalSize = size;
|
e->segmentMan->totalSize = size;
|
||||||
Segment seg;
|
e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE),
|
||||||
e->segmentMan->getSegment(seg, cuid);
|
e->segmentMan->totalSize);
|
||||||
e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath());
|
e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath());
|
||||||
createHttpDownloadCommand();
|
return prepareForRetry(0);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,8 +155,10 @@ bool HttpResponseCommand::handleOtherEncoding(const string& transferEncoding, co
|
||||||
e->segmentMan->isSplittable = false;
|
e->segmentMan->isSplittable = false;
|
||||||
e->segmentMan->filename = determinFilename(headers);
|
e->segmentMan->filename = determinFilename(headers);
|
||||||
e->segmentMan->totalSize = 0;
|
e->segmentMan->totalSize = 0;
|
||||||
Segment seg;
|
// disable keep-alive
|
||||||
e->segmentMan->getSegment(seg, cuid);
|
req->setKeepAlive(false);
|
||||||
|
Segment segment;
|
||||||
|
e->segmentMan->getSegment(segment, cuid);
|
||||||
e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath());
|
e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath());
|
||||||
createHttpDownloadCommand(transferEncoding);
|
createHttpDownloadCommand(transferEncoding);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -39,7 +39,7 @@ private:
|
||||||
string determinFilename(const HttpHeader& headers);
|
string determinFilename(const HttpHeader& headers);
|
||||||
HttpConnection* http;
|
HttpConnection* http;
|
||||||
protected:
|
protected:
|
||||||
bool executeInternal(Segment segment);
|
bool executeInternal(Segment& segment);
|
||||||
public:
|
public:
|
||||||
HttpResponseCommand(int cuid, Request* req, DownloadEngine* e,
|
HttpResponseCommand(int cuid, Request* req, DownloadEngine* e,
|
||||||
const SocketHandle& s);
|
const SocketHandle& s);
|
||||||
|
|
|
@ -23,11 +23,8 @@ SRCS = Socket.h\
|
||||||
SleepCommand.cc SleepCommand.h\
|
SleepCommand.cc SleepCommand.h\
|
||||||
DownloadEngine.cc DownloadEngine.h\
|
DownloadEngine.cc DownloadEngine.h\
|
||||||
ConsoleDownloadEngine.cc ConsoleDownloadEngine.h\
|
ConsoleDownloadEngine.cc ConsoleDownloadEngine.h\
|
||||||
Segment.h\
|
Segment.cc Segment.h\
|
||||||
SegmentMan.cc SegmentMan.h\
|
SegmentMan.cc SegmentMan.h\
|
||||||
SegmentSplitter.cc SegmentSplitter.h\
|
|
||||||
SplitFirstSegmentSplitter.cc SplitFirstSegmentSplitter.h\
|
|
||||||
SplitSlowestSegmentSplitter.cc SplitSlowestSegmentSplitter.h\
|
|
||||||
Util.cc Util.h\
|
Util.cc Util.h\
|
||||||
Request.cc Request.h\
|
Request.cc Request.h\
|
||||||
common.h\
|
common.h\
|
||||||
|
@ -55,7 +52,9 @@ SRCS = Socket.h\
|
||||||
FeatureConfig.cc FeatureConfig.h\
|
FeatureConfig.cc FeatureConfig.h\
|
||||||
DownloadEngineFactory.cc DownloadEngineFactory.h\
|
DownloadEngineFactory.cc DownloadEngineFactory.h\
|
||||||
RequestInfo.h\
|
RequestInfo.h\
|
||||||
UrlRequestInfo.cc UrlRequestInfo.h
|
UrlRequestInfo.cc UrlRequestInfo.h\
|
||||||
|
SpeedCalc.cc SpeedCalc.h\
|
||||||
|
PeerStat.h
|
||||||
|
|
||||||
if ENABLE_ASYNC_DNS
|
if ENABLE_ASYNC_DNS
|
||||||
SRCS += NameResolver.cc NameResolver.h
|
SRCS += NameResolver.cc NameResolver.h
|
||||||
|
|
|
@ -151,26 +151,24 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
||||||
FtpTunnelRequestCommand.h FtpTunnelResponseCommand.cc \
|
FtpTunnelRequestCommand.h FtpTunnelResponseCommand.cc \
|
||||||
FtpTunnelResponseCommand.h SleepCommand.cc SleepCommand.h \
|
FtpTunnelResponseCommand.h SleepCommand.cc SleepCommand.h \
|
||||||
DownloadEngine.cc DownloadEngine.h ConsoleDownloadEngine.cc \
|
DownloadEngine.cc DownloadEngine.h ConsoleDownloadEngine.cc \
|
||||||
ConsoleDownloadEngine.h Segment.h SegmentMan.cc SegmentMan.h \
|
ConsoleDownloadEngine.h Segment.cc Segment.h SegmentMan.cc \
|
||||||
SegmentSplitter.cc SegmentSplitter.h \
|
SegmentMan.h Util.cc Util.h Request.cc Request.h common.h \
|
||||||
SplitFirstSegmentSplitter.cc SplitFirstSegmentSplitter.h \
|
message.h Exception.h DlAbortEx.h DlRetryEx.h Logger.h \
|
||||||
SplitSlowestSegmentSplitter.cc SplitSlowestSegmentSplitter.h \
|
SimpleLogger.cc SimpleLogger.h TransferEncoding.h \
|
||||||
Util.cc Util.h Request.cc Request.h common.h message.h \
|
ChunkedEncoding.cc ChunkedEncoding.h DiskWriter.h \
|
||||||
Exception.h DlAbortEx.h DlRetryEx.h Logger.h SimpleLogger.cc \
|
DefaultDiskWriter.cc DefaultDiskWriter.h \
|
||||||
SimpleLogger.h TransferEncoding.h ChunkedEncoding.cc \
|
PreAllocationDiskWriter.cc PreAllocationDiskWriter.h \
|
||||||
ChunkedEncoding.h DiskWriter.h DefaultDiskWriter.cc \
|
AbstractDiskWriter.cc AbstractDiskWriter.h File.cc File.h \
|
||||||
DefaultDiskWriter.h PreAllocationDiskWriter.cc \
|
Option.cc Option.h Base64.cc Base64.h CookieBox.cc CookieBox.h \
|
||||||
PreAllocationDiskWriter.h AbstractDiskWriter.cc \
|
messageDigest.h LogFactory.cc LogFactory.h NullLogger.h \
|
||||||
AbstractDiskWriter.h File.cc File.h Option.cc Option.h \
|
TimeA2.cc TimeA2.h SharedHandle.h FeatureConfig.cc \
|
||||||
Base64.cc Base64.h CookieBox.cc CookieBox.h messageDigest.h \
|
FeatureConfig.h DownloadEngineFactory.cc \
|
||||||
LogFactory.cc LogFactory.h NullLogger.h TimeA2.cc TimeA2.h \
|
DownloadEngineFactory.h RequestInfo.h UrlRequestInfo.cc \
|
||||||
SharedHandle.h FeatureConfig.cc FeatureConfig.h \
|
UrlRequestInfo.h SpeedCalc.cc SpeedCalc.h PeerStat.h \
|
||||||
DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \
|
NameResolver.cc NameResolver.h MetaEntry.h Data.cc Data.h \
|
||||||
UrlRequestInfo.cc UrlRequestInfo.h NameResolver.cc \
|
Dictionary.cc Dictionary.h List.cc List.h MetaFileUtil.cc \
|
||||||
NameResolver.h MetaEntry.h Data.cc Data.h Dictionary.cc \
|
MetaFileUtil.h MetaEntryVisitor.h ShaVisitor.cc ShaVisitor.h \
|
||||||
Dictionary.h List.cc List.h MetaFileUtil.cc MetaFileUtil.h \
|
TorrentMan.cc TorrentMan.h PeerConnection.cc PeerConnection.h \
|
||||||
MetaEntryVisitor.h ShaVisitor.cc ShaVisitor.h TorrentMan.cc \
|
|
||||||
TorrentMan.h PeerConnection.cc PeerConnection.h \
|
|
||||||
PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \
|
PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \
|
||||||
PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \
|
PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \
|
||||||
PeerInitiateConnectionCommand.h PeerInteractionCommand.cc \
|
PeerInitiateConnectionCommand.h PeerInteractionCommand.cc \
|
||||||
|
@ -280,17 +278,15 @@ am__objects_4 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
|
||||||
FtpTunnelRequestCommand.$(OBJEXT) \
|
FtpTunnelRequestCommand.$(OBJEXT) \
|
||||||
FtpTunnelResponseCommand.$(OBJEXT) SleepCommand.$(OBJEXT) \
|
FtpTunnelResponseCommand.$(OBJEXT) SleepCommand.$(OBJEXT) \
|
||||||
DownloadEngine.$(OBJEXT) ConsoleDownloadEngine.$(OBJEXT) \
|
DownloadEngine.$(OBJEXT) ConsoleDownloadEngine.$(OBJEXT) \
|
||||||
SegmentMan.$(OBJEXT) SegmentSplitter.$(OBJEXT) \
|
Segment.$(OBJEXT) SegmentMan.$(OBJEXT) Util.$(OBJEXT) \
|
||||||
SplitFirstSegmentSplitter.$(OBJEXT) \
|
|
||||||
SplitSlowestSegmentSplitter.$(OBJEXT) Util.$(OBJEXT) \
|
|
||||||
Request.$(OBJEXT) SimpleLogger.$(OBJEXT) \
|
Request.$(OBJEXT) SimpleLogger.$(OBJEXT) \
|
||||||
ChunkedEncoding.$(OBJEXT) DefaultDiskWriter.$(OBJEXT) \
|
ChunkedEncoding.$(OBJEXT) DefaultDiskWriter.$(OBJEXT) \
|
||||||
PreAllocationDiskWriter.$(OBJEXT) AbstractDiskWriter.$(OBJEXT) \
|
PreAllocationDiskWriter.$(OBJEXT) AbstractDiskWriter.$(OBJEXT) \
|
||||||
File.$(OBJEXT) Option.$(OBJEXT) Base64.$(OBJEXT) \
|
File.$(OBJEXT) Option.$(OBJEXT) Base64.$(OBJEXT) \
|
||||||
CookieBox.$(OBJEXT) LogFactory.$(OBJEXT) TimeA2.$(OBJEXT) \
|
CookieBox.$(OBJEXT) LogFactory.$(OBJEXT) TimeA2.$(OBJEXT) \
|
||||||
FeatureConfig.$(OBJEXT) DownloadEngineFactory.$(OBJEXT) \
|
FeatureConfig.$(OBJEXT) DownloadEngineFactory.$(OBJEXT) \
|
||||||
UrlRequestInfo.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
|
UrlRequestInfo.$(OBJEXT) SpeedCalc.$(OBJEXT) $(am__objects_1) \
|
||||||
$(am__objects_3)
|
$(am__objects_2) $(am__objects_3)
|
||||||
am_libaria2c_a_OBJECTS = $(am__objects_4)
|
am_libaria2c_a_OBJECTS = $(am__objects_4)
|
||||||
libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
|
libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
|
||||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||||
|
@ -472,23 +468,21 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \
|
||||||
FtpTunnelRequestCommand.h FtpTunnelResponseCommand.cc \
|
FtpTunnelRequestCommand.h FtpTunnelResponseCommand.cc \
|
||||||
FtpTunnelResponseCommand.h SleepCommand.cc SleepCommand.h \
|
FtpTunnelResponseCommand.h SleepCommand.cc SleepCommand.h \
|
||||||
DownloadEngine.cc DownloadEngine.h ConsoleDownloadEngine.cc \
|
DownloadEngine.cc DownloadEngine.h ConsoleDownloadEngine.cc \
|
||||||
ConsoleDownloadEngine.h Segment.h SegmentMan.cc SegmentMan.h \
|
ConsoleDownloadEngine.h Segment.cc Segment.h SegmentMan.cc \
|
||||||
SegmentSplitter.cc SegmentSplitter.h \
|
SegmentMan.h Util.cc Util.h Request.cc Request.h common.h \
|
||||||
SplitFirstSegmentSplitter.cc SplitFirstSegmentSplitter.h \
|
message.h Exception.h DlAbortEx.h DlRetryEx.h Logger.h \
|
||||||
SplitSlowestSegmentSplitter.cc SplitSlowestSegmentSplitter.h \
|
SimpleLogger.cc SimpleLogger.h TransferEncoding.h \
|
||||||
Util.cc Util.h Request.cc Request.h common.h message.h \
|
ChunkedEncoding.cc ChunkedEncoding.h DiskWriter.h \
|
||||||
Exception.h DlAbortEx.h DlRetryEx.h Logger.h SimpleLogger.cc \
|
DefaultDiskWriter.cc DefaultDiskWriter.h \
|
||||||
SimpleLogger.h TransferEncoding.h ChunkedEncoding.cc \
|
PreAllocationDiskWriter.cc PreAllocationDiskWriter.h \
|
||||||
ChunkedEncoding.h DiskWriter.h DefaultDiskWriter.cc \
|
AbstractDiskWriter.cc AbstractDiskWriter.h File.cc File.h \
|
||||||
DefaultDiskWriter.h PreAllocationDiskWriter.cc \
|
Option.cc Option.h Base64.cc Base64.h CookieBox.cc CookieBox.h \
|
||||||
PreAllocationDiskWriter.h AbstractDiskWriter.cc \
|
messageDigest.h LogFactory.cc LogFactory.h NullLogger.h \
|
||||||
AbstractDiskWriter.h File.cc File.h Option.cc Option.h \
|
TimeA2.cc TimeA2.h SharedHandle.h FeatureConfig.cc \
|
||||||
Base64.cc Base64.h CookieBox.cc CookieBox.h messageDigest.h \
|
FeatureConfig.h DownloadEngineFactory.cc \
|
||||||
LogFactory.cc LogFactory.h NullLogger.h TimeA2.cc TimeA2.h \
|
DownloadEngineFactory.h RequestInfo.h UrlRequestInfo.cc \
|
||||||
SharedHandle.h FeatureConfig.cc FeatureConfig.h \
|
UrlRequestInfo.h SpeedCalc.cc SpeedCalc.h PeerStat.h \
|
||||||
DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \
|
$(am__append_1) $(am__append_2) $(am__append_3)
|
||||||
UrlRequestInfo.cc UrlRequestInfo.h $(am__append_1) \
|
|
||||||
$(am__append_2) $(am__append_3)
|
|
||||||
noinst_LIBRARIES = libaria2c.a
|
noinst_LIBRARIES = libaria2c.a
|
||||||
libaria2c_a_SOURCES = $(SRCS)
|
libaria2c_a_SOURCES = $(SRCS)
|
||||||
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
|
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
|
||||||
|
@ -655,15 +649,14 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestMessage.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestSlot.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)/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)/SegmentMan.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentSplitter.Po@am__quote@
|
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShaVisitor.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShaVisitor.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleLogger.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleLogger.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimplePeerMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimplePeerMessage.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SleepCommand.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)/SocketCore.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SplitFirstSegmentSplitter.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SpeedCalc.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SplitSlowestSegmentSplitter.Po@am__quote@
|
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SuggestPieceMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SuggestPieceMessage.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeA2.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeA2.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentAutoSaveCommand.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentAutoSaveCommand.Po@am__quote@
|
||||||
|
|
|
@ -127,7 +127,11 @@ bool PeerInteractionCommand::executeInternal() {
|
||||||
}
|
}
|
||||||
receiveMessages();
|
receiveMessages();
|
||||||
|
|
||||||
peerInteraction->addRequests();
|
int maxSpeedLimit = e->option->getAsInt(PREF_MAX_SPEED_LIMIT);
|
||||||
|
if(maxSpeedLimit == 0 ||
|
||||||
|
maxSpeedLimit > 0 && maxSpeedLimit <= e->getDownloadSpeed()) {
|
||||||
|
peerInteraction->addRequests();
|
||||||
|
}
|
||||||
peerInteraction->sendMessages(e->getUploadSpeed());
|
peerInteraction->sendMessages(e->getUploadSpeed());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - a simple utility for downloading files faster
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#ifndef _D_PEER_STAT_H_
|
||||||
|
#define _D_PEER_STAT_H_
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "SpeedCalc.h"
|
||||||
|
#include "SharedHandle.h"
|
||||||
|
|
||||||
|
class PeerStat {
|
||||||
|
public:
|
||||||
|
enum STATUS {
|
||||||
|
IDLE,
|
||||||
|
ACTIVE
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
int cuid;
|
||||||
|
SpeedCalc downloadSpeed;
|
||||||
|
Time downloadStartTime;
|
||||||
|
STATUS status;
|
||||||
|
public:
|
||||||
|
|
||||||
|
PeerStat(int cuid):cuid(cuid), status(IDLE) {}
|
||||||
|
|
||||||
|
~PeerStat() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns current download speed in byte per sec.
|
||||||
|
*/
|
||||||
|
int calculateDownloadSpeed() {
|
||||||
|
return downloadSpeed.calculateSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateDownloadLength(int bytes) {
|
||||||
|
downloadSpeed.update(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getMaxSpeed() const {
|
||||||
|
return downloadSpeed.getMaxSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
downloadSpeed.reset();
|
||||||
|
downloadStartTime.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void downloadStart() {
|
||||||
|
reset();
|
||||||
|
status = ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void downloadStop() {
|
||||||
|
status = IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Time& getDownloadStartTime() const {
|
||||||
|
return downloadStartTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATUS getStatus() const {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getCuid() const {
|
||||||
|
return cuid;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef SharedHandle<PeerStat> PeerStatHandle;
|
||||||
|
|
||||||
|
#endif // _D_PEER_STAT_H_
|
|
@ -30,6 +30,7 @@ void Piece::completeBlock(int blockIndex) {
|
||||||
|
|
||||||
void Piece::clearAllBlock() {
|
void Piece::clearAllBlock() {
|
||||||
bitfield->clearAllBit();
|
bitfield->clearAllBit();
|
||||||
|
bitfield->clearAllUseBit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Piece::setAllBlock() {
|
void Piece::setAllBlock() {
|
||||||
|
|
|
@ -81,7 +81,6 @@ void PieceMessage::receivedAction() {
|
||||||
onGotNewPiece(piece);
|
onGotNewPiece(piece);
|
||||||
} else {
|
} else {
|
||||||
onGotWrongPiece(piece);
|
onGotWrongPiece(piece);
|
||||||
peerInteraction->abortPiece(piece);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,6 +211,7 @@ void PieceMessage::onGotWrongPiece(Piece& piece) {
|
||||||
erasePieceOnDisk(piece);
|
erasePieceOnDisk(piece);
|
||||||
piece.clearAllBlock();
|
piece.clearAllBlock();
|
||||||
torrentMan->updatePiece(piece);
|
torrentMan->updatePiece(piece);
|
||||||
|
peerInteraction->abortPiece(piece);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PieceMessage::erasePieceOnDisk(const Piece& piece) {
|
void PieceMessage::erasePieceOnDisk(const Piece& piece) {
|
||||||
|
|
|
@ -23,11 +23,7 @@
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "FeatureConfig.h"
|
#include "FeatureConfig.h"
|
||||||
|
|
||||||
Request::Request():port(0), tryCount(0), isTorrent(false) {
|
Request::Request():port(0), tryCount(0), keepAlive(true), isTorrent(false) {
|
||||||
seg.sp = 0;
|
|
||||||
seg.ep = 0;
|
|
||||||
seg.ds = 0;
|
|
||||||
seg.finish = false;
|
|
||||||
cookieBox = new CookieBox();
|
cookieBox = new CookieBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +38,7 @@ bool Request::setUrl(const string& url) {
|
||||||
|
|
||||||
bool Request::resetUrl() {
|
bool Request::resetUrl() {
|
||||||
previousUrl = referer;
|
previousUrl = referer;
|
||||||
|
segment = Segment();
|
||||||
return setUrl(url);
|
return setUrl(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
#define _D_REQUEST_H_
|
#define _D_REQUEST_H_
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <Segment.h>
|
|
||||||
#include "CookieBox.h"
|
#include "CookieBox.h"
|
||||||
|
#include "Segment.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -59,9 +59,10 @@ private:
|
||||||
string file;
|
string file;
|
||||||
int tryCount;
|
int tryCount;
|
||||||
int trackerEvent;
|
int trackerEvent;
|
||||||
|
bool keepAlive;
|
||||||
bool parseUrl(const string& url);
|
bool parseUrl(const string& url);
|
||||||
public:
|
public:
|
||||||
Segment seg;
|
Segment segment;
|
||||||
CookieBox* cookieBox;
|
CookieBox* cookieBox;
|
||||||
bool isTorrent;
|
bool isTorrent;
|
||||||
public:
|
public:
|
||||||
|
@ -91,7 +92,8 @@ public:
|
||||||
int getPort() const { return port; }
|
int getPort() const { return port; }
|
||||||
string getDir() const { return dir; }
|
string getDir() const { return dir; }
|
||||||
string getFile() const { return file;}
|
string getFile() const { return file;}
|
||||||
|
bool isKeepAlive() const { return keepAlive; }
|
||||||
|
void setKeepAlive(bool keepAlive) { this->keepAlive = keepAlive; }
|
||||||
void setTrackerEvent(int event) { trackerEvent = event; }
|
void setTrackerEvent(int event) { trackerEvent = event; }
|
||||||
int getTrackerEvent() const { return trackerEvent; }
|
int getTrackerEvent() const { return trackerEvent; }
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - a simple utility for downloading files faster
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
|
||||||
|
#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;
|
||||||
|
return o;
|
||||||
|
}
|
|
@ -27,27 +27,46 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
/**
|
class Segment {
|
||||||
* Segment represents a download segment.
|
public:
|
||||||
* sp, ep is a offset from a begining of a file.
|
int index;
|
||||||
* Therefore, if a file size is x, then 0 <= sp <= ep <= x-1.
|
int length;
|
||||||
* sp, ep is used in Http Range header.
|
int segmentLength;
|
||||||
* e.g. Range: bytes=sp-ep
|
int writtenLength;
|
||||||
* ds is downloaded bytes.
|
|
||||||
* If a download of this segement is complete, finish must be set to true.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
int cuid;
|
|
||||||
long long int sp;
|
|
||||||
long long int ep;
|
|
||||||
long long int ds;
|
|
||||||
int speed;
|
|
||||||
bool finish;
|
|
||||||
} Segment;
|
|
||||||
|
|
||||||
typedef deque<Segment> Segments;
|
Segment(int index, int length, int segmentLength, int writtenLength = 0)
|
||||||
|
:index(index), length(length), segmentLength(segmentLength),
|
||||||
|
writtenLength(writtenLength) {}
|
||||||
|
|
||||||
#define SEGMENT_EQUAL(X, Y) (X.cuid == Y.cuid && X.sp == Y.sp && X.ep == Y.ep && X.ds == Y.ds && X.finish == Y.finish ? true : false)
|
Segment():index(-1), length(0), segmentLength(0), writtenLength(0) {}
|
||||||
|
|
||||||
|
bool complete() const {
|
||||||
|
return length <= writtenLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isNull() const {
|
||||||
|
return index == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long int getPosition() const {
|
||||||
|
return ((long long int)index)*segmentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Segment& segment) const {
|
||||||
|
return index == segment.index &&
|
||||||
|
length == segment.length &&
|
||||||
|
segmentLength == segment.segmentLength &&
|
||||||
|
writtenLength == segment.writtenLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Segment& segment) const {
|
||||||
|
return !(*this == segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend ostream& operator<<(ostream& o, const Segment& segment);
|
||||||
|
};
|
||||||
|
|
||||||
|
ostream& operator<<(ostream& o, const Segment& segment);
|
||||||
|
|
||||||
#endif // _D_SEGMENT_H_
|
#endif // _D_SEGMENT_H_
|
||||||
|
|
||||||
|
|
|
@ -31,88 +31,21 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
SegmentMan::SegmentMan():totalSize(0),
|
SegmentMan::SegmentMan():bitfield(0),
|
||||||
|
totalSize(0),
|
||||||
isSplittable(true),
|
isSplittable(true),
|
||||||
downloadStarted(false),
|
downloadStarted(false),
|
||||||
dir("."),
|
dir("."),
|
||||||
errors(0),
|
errors(0),
|
||||||
splitter(NULL),
|
diskWriter(0) {
|
||||||
diskWriter(NULL) {
|
|
||||||
logger = LogFactory::getInstance();
|
logger = LogFactory::getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
SegmentMan::~SegmentMan() {
|
SegmentMan::~SegmentMan() {
|
||||||
if(splitter != NULL) {
|
delete bitfield;
|
||||||
delete splitter;
|
delete diskWriter;
|
||||||
}
|
|
||||||
if(diskWriter != NULL) {
|
|
||||||
delete diskWriter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SegmentMan::unregisterId(int cuid) {
|
|
||||||
for(Segments::iterator itr = segments.begin(); itr != segments.end(); itr++) {
|
|
||||||
if((*itr).cuid == cuid) {
|
|
||||||
cuid = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SegmentMan::getSegment(Segment& seg, int cuid) {
|
|
||||||
//Segment s = { 0, 0, 0, false };
|
|
||||||
|
|
||||||
if(segments.empty()) {
|
|
||||||
logger->debug(string("assign new segment { sp = 0, ep = "+(totalSize == 0 ? "0" : Util::llitos(totalSize-1))+" } to cuid "+Util::llitos(cuid)).c_str());
|
|
||||||
//seg = { cuid, 0, totalSize == 0 ? 0 : totalSize-1, 0, false };
|
|
||||||
seg.cuid = cuid;
|
|
||||||
seg.sp = 0;
|
|
||||||
seg.ep = totalSize == 0 ? 0 : totalSize-1;
|
|
||||||
seg.ds = 0;
|
|
||||||
seg.speed = 0;
|
|
||||||
seg.finish = false;
|
|
||||||
segments.push_back(seg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for(Segments::iterator itr = segments.begin(); itr != segments.end(); itr++) {
|
|
||||||
if((*itr).cuid == cuid && !(*itr).finish) {
|
|
||||||
// logger->debug("return an existing segment { "
|
|
||||||
// "sp = "+Util::ulitos((*itr).sp)+", "+
|
|
||||||
// "ep = "+Util::ulitos((*itr).ep)+", "
|
|
||||||
// "ds = "+Util::ulitos((*itr).ds)+" } to "+
|
|
||||||
// "cuid "+Util::ulitos((*itr).cuid));
|
|
||||||
seg = *itr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!isSplittable) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for(Segments::iterator itr = segments.begin(); itr != segments.end(); itr++) {
|
|
||||||
Segment& s = *itr;
|
|
||||||
if(s.finish) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(s.cuid == 0) {
|
|
||||||
s.cuid = cuid;
|
|
||||||
seg = s;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return splitter->splitSegment(seg, cuid, segments);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SegmentMan::updateSegment(const Segment& segment) {
|
|
||||||
for(Segments::iterator itr = segments.begin(); itr != segments.end(); itr++) {
|
|
||||||
if((*itr).cuid == segment.cuid &&
|
|
||||||
(*itr).sp == segment.sp &&
|
|
||||||
(*itr).ep == segment.ep) {
|
|
||||||
*itr = segment;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool SegmentMan::segmentFileExists() const {
|
bool SegmentMan::segmentFileExists() const {
|
||||||
if(!isSplittable) {
|
if(!isSplittable) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -144,10 +77,6 @@ void SegmentMan::load() {
|
||||||
segFilename.c_str(), strerror(errno));
|
segFilename.c_str(), strerror(errno));
|
||||||
}
|
}
|
||||||
logger->info(MSG_LOADED_SEGMENT_FILE);
|
logger->info(MSG_LOADED_SEGMENT_FILE);
|
||||||
for(Segments::iterator itr = segments.begin(); itr != segments.end();
|
|
||||||
itr++) {
|
|
||||||
(*itr).cuid = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SegmentMan::save() const {
|
void SegmentMan::save() const {
|
||||||
|
@ -161,8 +90,32 @@ void SegmentMan::save() const {
|
||||||
if(fwrite(&totalSize, sizeof(totalSize), 1, segFile) < 1) {
|
if(fwrite(&totalSize, sizeof(totalSize), 1, segFile) < 1) {
|
||||||
throw string("writeError");
|
throw string("writeError");
|
||||||
}
|
}
|
||||||
for(Segments::const_iterator itr = segments.begin(); itr != segments.end(); itr++) {
|
int segmentLength = bitfield->getBlockLength();
|
||||||
if(fwrite(&*itr, sizeof(Segment), 1, segFile) < 1) {
|
if(fwrite(&segmentLength, sizeof(segmentLength), 1, segFile) < 1) {
|
||||||
|
throw string("writeError");
|
||||||
|
}
|
||||||
|
if(bitfield) {
|
||||||
|
int 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 {
|
||||||
|
int i = 0;
|
||||||
|
if(fwrite(&i, sizeof(i), 1, segFile) < 1) {
|
||||||
|
throw string("writeError");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int 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, sizeof(Segment), 1, segFile) < 1) {
|
||||||
throw string("writeError");
|
throw string("writeError");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,16 +142,35 @@ void SegmentMan::read(FILE* file) {
|
||||||
if(fread(&totalSize, sizeof(totalSize), 1, file) < 1) {
|
if(fread(&totalSize, sizeof(totalSize), 1, file) < 1) {
|
||||||
throw string("readError");
|
throw string("readError");
|
||||||
}
|
}
|
||||||
while(1) {
|
int segmentSize;
|
||||||
|
if(fread(&segmentSize, sizeof(segmentSize), 1, file) < 1) {
|
||||||
|
throw string("readError");
|
||||||
|
}
|
||||||
|
int 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int segmentCount;
|
||||||
|
if(fread(&segmentCount, sizeof(segmentCount), 1, file) < 1) {
|
||||||
|
throw string("readError");
|
||||||
|
}
|
||||||
|
while(segmentCount--) {
|
||||||
Segment seg;
|
Segment seg;
|
||||||
if(fread(&seg, sizeof(Segment), 1, file) < 1) {
|
if(fread(&seg, sizeof(Segment), 1, file) < 1) {
|
||||||
if(ferror(file)) {
|
throw string("readError");
|
||||||
throw string("readError");
|
|
||||||
} else if(feof(file)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
segments.push_back(seg);
|
usedSegmentEntries.push_back(SegmentEntry(0, seg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,15 +185,14 @@ void SegmentMan::remove() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SegmentMan::finished() const {
|
bool SegmentMan::finished() const {
|
||||||
if(!downloadStarted || segments.size() == 0) {
|
if(!downloadStarted) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for(Segments::const_iterator itr = segments.begin(); itr != segments.end(); itr++) {
|
if(!bitfield) {
|
||||||
if(!(*itr).finish) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
assert(bitfield);
|
||||||
|
return bitfield->isAllBitSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SegmentMan::removeIfFinished() const {
|
void SegmentMan::removeIfFinished() const {
|
||||||
|
@ -230,19 +201,219 @@ void SegmentMan::removeIfFinished() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long long int SegmentMan::getDownloadedSize() const {
|
|
||||||
long long int size = 0;
|
|
||||||
for(Segments::const_iterator itr = segments.begin(); itr != segments.end(); itr++) {
|
|
||||||
size += (*itr).ds;
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SegmentMan::init() {
|
void SegmentMan::init() {
|
||||||
totalSize = 0;
|
totalSize = 0;
|
||||||
isSplittable = false;
|
isSplittable = false;
|
||||||
downloadStarted = false;
|
downloadStarted = false;
|
||||||
errors = 0;
|
errors = 0;
|
||||||
segments.clear();
|
//segments.clear();
|
||||||
|
usedSegmentEntries.clear();
|
||||||
|
delete bitfield;
|
||||||
|
peerStats.clear();
|
||||||
diskWriter->closeFile();
|
diskWriter->closeFile();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SegmentMan::initBitfield(int segmentLength, long long int totalLength) {
|
||||||
|
this->bitfield = new BitfieldMan(segmentLength, totalLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
class FindSegmentEntryByIndex {
|
||||||
|
private:
|
||||||
|
int index;
|
||||||
|
public:
|
||||||
|
FindSegmentEntryByIndex(int index):index(index) {}
|
||||||
|
|
||||||
|
bool operator()(const SegmentEntry& entry) {
|
||||||
|
return entry.segment.index == index;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FindSegmentEntryByCuid {
|
||||||
|
private:
|
||||||
|
int cuid;
|
||||||
|
public:
|
||||||
|
FindSegmentEntryByCuid(int cuid):cuid(cuid) {}
|
||||||
|
|
||||||
|
bool operator()(const SegmentEntry& entry) {
|
||||||
|
return entry.cuid == cuid;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Segment SegmentMan::checkoutSegment(int cuid, int index) {
|
||||||
|
logger->debug("Attach segment#%d to CUID#%d.", index, cuid);
|
||||||
|
bitfield->setUseBit(index);
|
||||||
|
|
||||||
|
SegmentEntries::iterator itr = find_if(usedSegmentEntries.begin(),
|
||||||
|
usedSegmentEntries.end(),
|
||||||
|
FindSegmentEntryByIndex(index));
|
||||||
|
Segment segment;
|
||||||
|
if(itr == usedSegmentEntries.end()) {
|
||||||
|
segment = Segment(index, bitfield->getBlockLength(index),
|
||||||
|
bitfield->getBlockLength());
|
||||||
|
SegmentEntry entry(cuid, segment);
|
||||||
|
usedSegmentEntries.push_back(entry);
|
||||||
|
} else {
|
||||||
|
(*itr).cuid = cuid;
|
||||||
|
segment = (*itr).segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger->debug("index=%d, length=%d, segmentLength=%d, writtenLength=%d",
|
||||||
|
segment.index, segment.length, segment.segmentLength,
|
||||||
|
segment.writtenLength);
|
||||||
|
return segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SegmentMan::onNullBitfield(Segment& segment, int cuid) {
|
||||||
|
if(usedSegmentEntries.size() == 0) {
|
||||||
|
segment = Segment(0, 0, 0);
|
||||||
|
usedSegmentEntries.push_back(SegmentEntry(cuid, segment));
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
SegmentEntries::iterator uitr = find_if(usedSegmentEntries.begin(),
|
||||||
|
usedSegmentEntries.end(),
|
||||||
|
FindSegmentEntryByCuid(cuid));
|
||||||
|
if(uitr == usedSegmentEntries.end()) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
segment = uitr->segment;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SegmentMan::getSegment(Segment& segment, int cuid) {
|
||||||
|
if(!bitfield) {
|
||||||
|
return onNullBitfield(segment, cuid);
|
||||||
|
}
|
||||||
|
SegmentEntries::iterator uitr = find_if(usedSegmentEntries.begin(),
|
||||||
|
usedSegmentEntries.end(),
|
||||||
|
FindSegmentEntryByCuid(cuid));
|
||||||
|
if(uitr != usedSegmentEntries.end()) {
|
||||||
|
segment = uitr->segment;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int index = bitfield->getSparseMissingUnusedIndex();
|
||||||
|
if(index == -1) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
segment = checkoutSegment(cuid, index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SegmentMan::getSegment(Segment& segment, int cuid, int index) {
|
||||||
|
if(!bitfield) {
|
||||||
|
return onNullBitfield(segment, cuid);
|
||||||
|
}
|
||||||
|
if(index < 0 || bitfield->countBlock() <= index) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(bitfield->isBitSet(index) || bitfield->isUseBitSet(index)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
segment = checkoutSegment(cuid, index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SegmentMan::updateSegment(int cuid, const Segment& segment) {
|
||||||
|
if(segment.isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SegmentEntries::iterator itr = find_if(usedSegmentEntries.begin(),
|
||||||
|
usedSegmentEntries.end(),
|
||||||
|
FindSegmentEntryByCuid(cuid));
|
||||||
|
if(itr == usedSegmentEntries.end()) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
(*itr).segment = segment;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CancelSegment {
|
||||||
|
private:
|
||||||
|
int cuid;
|
||||||
|
BitfieldMan* bitfield;
|
||||||
|
public:
|
||||||
|
CancelSegment(int cuid, BitfieldMan* bitfield):cuid(cuid),
|
||||||
|
bitfield(bitfield) {}
|
||||||
|
|
||||||
|
void operator()(SegmentEntry& entry) {
|
||||||
|
if(entry.cuid == cuid) {
|
||||||
|
bitfield->unsetUseBit(entry.segment.index);
|
||||||
|
entry.cuid = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void SegmentMan::cancelSegment(int cuid) {
|
||||||
|
if(bitfield) {
|
||||||
|
for_each(usedSegmentEntries.begin(), usedSegmentEntries.end(),
|
||||||
|
CancelSegment(cuid, bitfield));
|
||||||
|
} else {
|
||||||
|
usedSegmentEntries.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SegmentMan::completeSegment(int cuid, const Segment& 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();
|
||||||
|
}
|
||||||
|
SegmentEntries::iterator itr = find_if(usedSegmentEntries.begin(),
|
||||||
|
usedSegmentEntries.end(),
|
||||||
|
FindSegmentEntryByCuid(cuid));
|
||||||
|
if(itr == usedSegmentEntries.end()) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
usedSegmentEntries.erase(itr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SegmentMan::hasSegment(int index) const {
|
||||||
|
if(bitfield) {
|
||||||
|
return bitfield->isBitSet(index);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long long int SegmentMan::getDownloadLength() const {
|
||||||
|
long long int dlLength = 0;
|
||||||
|
if(bitfield) {
|
||||||
|
dlLength += bitfield->getCompletedLength();
|
||||||
|
}
|
||||||
|
for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
|
||||||
|
itr != usedSegmentEntries.end(); itr++) {
|
||||||
|
dlLength += itr->segment.writtenLength;
|
||||||
|
}
|
||||||
|
return dlLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SegmentMan::registerPeerStat(const PeerStatHandle& peerStat) {
|
||||||
|
PeerStatHandle temp = getPeerStat(peerStat->getCuid());
|
||||||
|
if(!temp.get()) {
|
||||||
|
peerStats.push_back(peerStat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SegmentMan::calculateDownloadSpeed() const {
|
||||||
|
int speed = 0;
|
||||||
|
for(PeerStats::const_iterator itr = peerStats.begin();
|
||||||
|
itr != peerStats.end(); itr++) {
|
||||||
|
const PeerStatHandle& peerStat = *itr;
|
||||||
|
if(peerStat->getStatus() == PeerStat::ACTIVE) {
|
||||||
|
speed += peerStat->calculateDownloadSpeed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return speed;
|
||||||
}
|
}
|
||||||
|
|
130
src/SegmentMan.h
130
src/SegmentMan.h
|
@ -26,23 +26,42 @@
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "Segment.h"
|
#include "Segment.h"
|
||||||
#include "Option.h"
|
#include "Option.h"
|
||||||
#include "SegmentSplitter.h"
|
|
||||||
#include "DiskWriter.h"
|
#include "DiskWriter.h"
|
||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
|
#include "BitfieldMan.h"
|
||||||
|
#include "PeerStat.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#define SEGMENT_FILE_EXTENSION ".aria2"
|
#define SEGMENT_FILE_EXTENSION ".aria2"
|
||||||
|
|
||||||
|
class SegmentEntry {
|
||||||
|
public:
|
||||||
|
int cuid;
|
||||||
|
Segment segment;
|
||||||
|
public:
|
||||||
|
SegmentEntry(int cuid, const Segment& segment)
|
||||||
|
:cuid(cuid), segment(segment) {}
|
||||||
|
~SegmentEntry() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef deque<SegmentEntry> SegmentEntries;
|
||||||
|
typedef deque<PeerStatHandle> PeerStats;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class holds the download progress of the one download entry.
|
* This class holds the download progress of the one download entry.
|
||||||
*/
|
*/
|
||||||
class SegmentMan {
|
class SegmentMan {
|
||||||
private:
|
private:
|
||||||
const Logger* logger;
|
const Logger* logger;
|
||||||
|
BitfieldMan* bitfield;
|
||||||
|
SegmentEntries usedSegmentEntries;
|
||||||
|
PeerStats peerStats;
|
||||||
|
|
||||||
void read(FILE* file);
|
void read(FILE* file);
|
||||||
FILE* openSegFile(const string& segFilename, const string& mode) const;
|
FILE* openSegFile(const string& segFilename, const string& mode) const;
|
||||||
|
bool onNullBitfield(Segment& segment, int cuid);
|
||||||
|
Segment checkoutSegment(int cuid, int index);
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* The total number of bytes to download.
|
* The total number of bytes to download.
|
||||||
|
@ -65,10 +84,6 @@ public:
|
||||||
* The default value is false.
|
* The default value is false.
|
||||||
*/
|
*/
|
||||||
bool downloadStarted;
|
bool downloadStarted;
|
||||||
/**
|
|
||||||
* Holds segments.
|
|
||||||
*/
|
|
||||||
Segments segments;
|
|
||||||
/**
|
/**
|
||||||
* Respresents the file name of the downloaded file.
|
* Respresents the file name of the downloaded file.
|
||||||
* If the URL does not contain file name part(http://www.rednoah.com/, for
|
* If the URL does not contain file name part(http://www.rednoah.com/, for
|
||||||
|
@ -91,7 +106,6 @@ public:
|
||||||
int errors;
|
int errors;
|
||||||
|
|
||||||
const Option* option;
|
const Option* option;
|
||||||
SegmentSplitter* splitter;
|
|
||||||
DiskWriter* diskWriter;
|
DiskWriter* diskWriter;
|
||||||
Requests reserved;
|
Requests reserved;
|
||||||
|
|
||||||
|
@ -116,31 +130,6 @@ public:
|
||||||
return getFilePath()+SEGMENT_FILE_EXTENSION;
|
return getFilePath()+SEGMENT_FILE_EXTENSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the cuid of the holded segments with specified cuid to 0.
|
|
||||||
*/
|
|
||||||
void unregisterId(int cuid);
|
|
||||||
/**
|
|
||||||
* There is a segment available for DownloadCommand specified by cuid,
|
|
||||||
* fills segment and returns true.
|
|
||||||
* There is no segment available, then returns false and segment is
|
|
||||||
* undefined in this case.
|
|
||||||
*
|
|
||||||
* @param segment segment to attach for cuid.
|
|
||||||
* @param cuid cuid of DownloadCommand.
|
|
||||||
* @returns true: there is a segment available, false: there is no segment
|
|
||||||
* available.
|
|
||||||
*/
|
|
||||||
bool getSegment(Segment& segment, int cuid);
|
|
||||||
/**
|
|
||||||
* Updates the ds value of the specified segment.
|
|
||||||
* Only a segment x is updated where x.sp == sgment.sp && x.ep ==
|
|
||||||
* segment.ep && x.ds == segment.ds &&x.cuid == segment.cuid
|
|
||||||
* is true.
|
|
||||||
*
|
|
||||||
* @param segment segment to update
|
|
||||||
*/
|
|
||||||
void updateSegment(const Segment& segment);
|
|
||||||
/**
|
/**
|
||||||
* Returns true only if the segment data file exists.
|
* Returns true only if the segment data file exists.
|
||||||
* The file name of the segment data is filename appended by ".aria2".
|
* The file name of the segment data is filename appended by ".aria2".
|
||||||
|
@ -173,9 +162,84 @@ public:
|
||||||
*/
|
*/
|
||||||
void removeIfFinished() const;
|
void removeIfFinished() const;
|
||||||
/**
|
/**
|
||||||
* Returns the total number of bytes to be downloaded.
|
* Returns a vacant segment.
|
||||||
|
* If there is no vacant segment, then returns a segment instance whose
|
||||||
|
* isNull call is true.
|
||||||
*/
|
*/
|
||||||
long long int getDownloadedSize() const;
|
bool getSegment(Segment& segment, int cuid);
|
||||||
|
/**
|
||||||
|
* Returns a segment whose index is index.
|
||||||
|
* If it has already assigned
|
||||||
|
* to another cuid or has been downloaded, then returns a segment instance
|
||||||
|
* whose isNull call is true.
|
||||||
|
*/
|
||||||
|
bool getSegment(Segment& segment, int cuid, int index);
|
||||||
|
/**
|
||||||
|
* Updates download status.
|
||||||
|
*/
|
||||||
|
bool updateSegment(int cuid, const Segment& segment);
|
||||||
|
/**
|
||||||
|
* Cancels all the segment which the command having given cuid
|
||||||
|
* uses.
|
||||||
|
*/
|
||||||
|
void cancelSegment(int cuid);
|
||||||
|
/**
|
||||||
|
* Tells SegmentMan that the segment has been downloaded successfully.
|
||||||
|
*/
|
||||||
|
bool completeSegment(int cuid, const Segment& segment);
|
||||||
|
/**
|
||||||
|
* Initializes bitfield with the provided length parameters.
|
||||||
|
*/
|
||||||
|
void initBitfield(int segmentLength, long long int totalLength);
|
||||||
|
/**
|
||||||
|
* Returns true if the segment whose index is index has been downloaded.
|
||||||
|
*/
|
||||||
|
bool hasSegment(int index) const;
|
||||||
|
/**
|
||||||
|
* Returns the length of bytes downloaded.
|
||||||
|
*/
|
||||||
|
long long int getDownloadLength() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers given peerStat if it has not been registerd.
|
||||||
|
* Otherwise does nothing.
|
||||||
|
*/
|
||||||
|
void registerPeerStat(const PeerStatHandle& peerStat);
|
||||||
|
|
||||||
|
class FindPeerStat {
|
||||||
|
private:
|
||||||
|
int cuid;
|
||||||
|
public:
|
||||||
|
FindPeerStat(int cuid):cuid(cuid) {}
|
||||||
|
|
||||||
|
bool operator()(const PeerStatHandle& peerStat) {
|
||||||
|
if(peerStat->getCuid() == cuid) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns peerStat whose cuid is given cuid. If it is not found, returns
|
||||||
|
* PeerStatHandle(0).
|
||||||
|
*/
|
||||||
|
PeerStatHandle getPeerStat(int cuid) const {
|
||||||
|
PeerStats::const_iterator itr = find_if(peerStats.begin(), peerStats.end(),
|
||||||
|
FindPeerStat(cuid));
|
||||||
|
if(itr == peerStats.end()) {
|
||||||
|
// TODO
|
||||||
|
return PeerStatHandle(0);
|
||||||
|
} else {
|
||||||
|
return *itr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns current download speed in bytes per sec.
|
||||||
|
*/
|
||||||
|
int calculateDownloadSpeed() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _D_SEGMENT_MAN_H_
|
#endif // _D_SEGMENT_MAN_H_
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - a simple utility for downloading files faster
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#include "SpeedCalc.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <ostream>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
#define CHANGE_INTERVAL_SEC 15
|
||||||
|
|
||||||
|
class Reset {
|
||||||
|
public:
|
||||||
|
void operator()(Time& tm) {
|
||||||
|
tm.reset();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void SpeedCalc::reset() {
|
||||||
|
fill(&lengthArray[0], &lengthArray[2], 0);
|
||||||
|
for_each(&cpArray[0], &cpArray[2], Reset());
|
||||||
|
sw = 0;
|
||||||
|
maxSpeed = 0;
|
||||||
|
prevSpeed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SpeedCalc::calculateSpeed() {
|
||||||
|
int milliElapsed = cpArray[sw].differenceInMillis();
|
||||||
|
if(milliElapsed) {
|
||||||
|
int speed = lengthArray[sw]*1000/milliElapsed;
|
||||||
|
prevSpeed = speed;
|
||||||
|
maxSpeed = max<int>(speed, maxSpeed);
|
||||||
|
return speed;
|
||||||
|
} else {
|
||||||
|
return prevSpeed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Plus {
|
||||||
|
private:
|
||||||
|
int d;
|
||||||
|
public:
|
||||||
|
Plus(int d):d(d) {}
|
||||||
|
|
||||||
|
void operator()(long long int& length) {
|
||||||
|
length += d;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void SpeedCalc::update(int bytes) {
|
||||||
|
for_each(&lengthArray[0], &lengthArray[2], Plus(bytes));
|
||||||
|
if(isIntervalOver()) {
|
||||||
|
changeSw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SpeedCalc::isIntervalOver() const {
|
||||||
|
return CHANGE_INTERVAL_SEC <= cpArray[sw].difference();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpeedCalc::changeSw() {
|
||||||
|
lengthArray[sw] = 0;
|
||||||
|
cpArray[sw].reset();
|
||||||
|
sw ^= 0x01;
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - a simple utility for downloading files faster
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#ifndef _D_SPEED_CALC_H_
|
||||||
|
#define _D_SPEED_CALC_H_
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "TimeA2.h"
|
||||||
|
|
||||||
|
class SpeedCalc {
|
||||||
|
private:
|
||||||
|
long long int lengthArray[2];
|
||||||
|
int sw;
|
||||||
|
Time cpArray[2];
|
||||||
|
int maxSpeed;
|
||||||
|
int prevSpeed;
|
||||||
|
|
||||||
|
bool isIntervalOver() const;
|
||||||
|
void changeSw();
|
||||||
|
public:
|
||||||
|
SpeedCalc() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
~SpeedCalc() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns download/upload speed in byte per sec
|
||||||
|
*/
|
||||||
|
int calculateSpeed();
|
||||||
|
|
||||||
|
int getMaxSpeed() const {
|
||||||
|
return maxSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(int bytes);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _D_SPEED_CALC_H_
|
|
@ -22,7 +22,6 @@
|
||||||
#include "HttpInitiateConnectionCommand.h"
|
#include "HttpInitiateConnectionCommand.h"
|
||||||
#include "ConsoleDownloadEngine.h"
|
#include "ConsoleDownloadEngine.h"
|
||||||
#include "SegmentMan.h"
|
#include "SegmentMan.h"
|
||||||
#include "SplitSlowestSegmentSplitter.h"
|
|
||||||
#include "LogFactory.h"
|
#include "LogFactory.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "DefaultDiskWriter.h"
|
#include "DefaultDiskWriter.h"
|
||||||
|
@ -272,6 +271,8 @@ int main(int argc, char* argv[]) {
|
||||||
op->put(PREF_DIR, ".");
|
op->put(PREF_DIR, ".");
|
||||||
op->put(PREF_SPLIT, "1");
|
op->put(PREF_SPLIT, "1");
|
||||||
op->put(PREF_DAEMON, V_FALSE);
|
op->put(PREF_DAEMON, V_FALSE);
|
||||||
|
op->put(PREF_SEGMENT_SIZE, Util::itos(1024*1024));
|
||||||
|
op->put(PREF_HTTP_KEEP_ALIVE, V_FALSE);
|
||||||
op->put(PREF_LISTEN_PORT, "-1");
|
op->put(PREF_LISTEN_PORT, "-1");
|
||||||
op->put(PREF_METALINK_SERVERS, "15");
|
op->put(PREF_METALINK_SERVERS, "15");
|
||||||
op->put(PREF_FOLLOW_TORRENT,
|
op->put(PREF_FOLLOW_TORRENT,
|
||||||
|
@ -303,6 +304,7 @@ int main(int argc, char* argv[]) {
|
||||||
op->put(PREF_DIRECT_FILE_MAPPING, V_TRUE);
|
op->put(PREF_DIRECT_FILE_MAPPING, V_TRUE);
|
||||||
op->put(PREF_UPLOAD_LIMIT, "0");
|
op->put(PREF_UPLOAD_LIMIT, "0");
|
||||||
op->put(PREF_LOWEST_SPEED_LIMIT, "0");
|
op->put(PREF_LOWEST_SPEED_LIMIT, "0");
|
||||||
|
op->put(PREF_MAX_SPEED_LIMIT, "0");
|
||||||
while(1) {
|
while(1) {
|
||||||
int optIndex = 0;
|
int optIndex = 0;
|
||||||
int lopt;
|
int lopt;
|
||||||
|
|
|
@ -57,8 +57,12 @@
|
||||||
#define PREF_DAEMON "daemon"
|
#define PREF_DAEMON "daemon"
|
||||||
// value: a string
|
// value: a string
|
||||||
#define PREF_REFERER "referer"
|
#define PREF_REFERER "referer"
|
||||||
// value' 1*digit
|
// value: 1*digit
|
||||||
#define PREF_LOWEST_SPEED_LIMIT "lowest_speed_limit"
|
#define PREF_LOWEST_SPEED_LIMIT "lowest_speed_limit"
|
||||||
|
// value: 1*digit
|
||||||
|
#define PREF_SEGMENT_SIZE "segment_size"
|
||||||
|
// value: 1*digit
|
||||||
|
#define PREF_MAX_SPEED_LIMIT "max_speed_limit"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FTP related preferences
|
* FTP related preferences
|
||||||
|
@ -86,6 +90,8 @@
|
||||||
# define V_BASIC "basic"
|
# define V_BASIC "basic"
|
||||||
// values: true | false
|
// values: true | false
|
||||||
#define PREF_HTTP_AUTH_ENABLED "http_auth_enabled"
|
#define PREF_HTTP_AUTH_ENABLED "http_auth_enabled"
|
||||||
|
// values: true | false
|
||||||
|
#define PREF_HTTP_KEEP_ALIVE "http_keep_alive"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP proxy related preferences
|
* HTTP proxy related preferences
|
||||||
|
|
|
@ -12,6 +12,7 @@ class BitfieldManTest:public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testIsAllBitSet);
|
CPPUNIT_TEST(testIsAllBitSet);
|
||||||
CPPUNIT_TEST(testFilter);
|
CPPUNIT_TEST(testFilter);
|
||||||
CPPUNIT_TEST(testGetMissingIndex);
|
CPPUNIT_TEST(testGetMissingIndex);
|
||||||
|
CPPUNIT_TEST(testGetSparceMissingUnusedIndex);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -24,6 +25,7 @@ public:
|
||||||
void testIsAllBitSet();
|
void testIsAllBitSet();
|
||||||
void testFilter();
|
void testFilter();
|
||||||
void testGetMissingIndex();
|
void testGetMissingIndex();
|
||||||
|
void testGetSparceMissingUnusedIndex();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,3 +211,29 @@ void BitfieldManTest::testGetMissingIndex() {
|
||||||
CPPUNIT_ASSERT_EQUAL(-1, bt1.getMissingIndex(bitArray5, 32));
|
CPPUNIT_ASSERT_EQUAL(-1, bt1.getMissingIndex(bitArray5, 32));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BitfieldManTest::testGetSparceMissingUnusedIndex() {
|
||||||
|
BitfieldMan bitfield(1024*1024, 10*1024*1024);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(0, bitfield.getSparseMissingUnusedIndex());
|
||||||
|
bitfield.setBit(0);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(5, bitfield.getSparseMissingUnusedIndex());
|
||||||
|
bitfield.setUseBit(5);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(3, bitfield.getSparseMissingUnusedIndex());
|
||||||
|
bitfield.setBit(3);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(8, bitfield.getSparseMissingUnusedIndex());
|
||||||
|
bitfield.setBit(8);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(2, bitfield.getSparseMissingUnusedIndex());
|
||||||
|
bitfield.setBit(2);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(7, bitfield.getSparseMissingUnusedIndex());
|
||||||
|
bitfield.setBit(7);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, bitfield.getSparseMissingUnusedIndex());
|
||||||
|
bitfield.setBit(1);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(4, bitfield.getSparseMissingUnusedIndex());
|
||||||
|
bitfield.setBit(4);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(6, bitfield.getSparseMissingUnusedIndex());
|
||||||
|
bitfield.setBit(6);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(9, bitfield.getSparseMissingUnusedIndex());
|
||||||
|
bitfield.setBit(9);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(-1, bitfield.getSparseMissingUnusedIndex());
|
||||||
|
}
|
||||||
|
|
|
@ -37,7 +37,9 @@ aria2c_SOURCES = AllTest.cc\
|
||||||
MetalinkEntryTest.cc\
|
MetalinkEntryTest.cc\
|
||||||
FeatureConfigTest.cc\
|
FeatureConfigTest.cc\
|
||||||
ShareRatioSeedCriteriaTest.cc\
|
ShareRatioSeedCriteriaTest.cc\
|
||||||
TimeSeedCriteriaTest.cc
|
TimeSeedCriteriaTest.cc\
|
||||||
|
SegmentManTest.cc\
|
||||||
|
SpeedCalcTest.cc
|
||||||
#aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
|
#aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
|
||||||
#aria2c_LDFLAGS = ${CPPUNIT_LIBS}
|
#aria2c_LDFLAGS = ${CPPUNIT_LIBS}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,8 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) RequestTest.$(OBJEXT) \
|
||||||
Xml2MetalinkProcessorTest.$(OBJEXT) MetalinkerTest.$(OBJEXT) \
|
Xml2MetalinkProcessorTest.$(OBJEXT) MetalinkerTest.$(OBJEXT) \
|
||||||
MetalinkEntryTest.$(OBJEXT) FeatureConfigTest.$(OBJEXT) \
|
MetalinkEntryTest.$(OBJEXT) FeatureConfigTest.$(OBJEXT) \
|
||||||
ShareRatioSeedCriteriaTest.$(OBJEXT) \
|
ShareRatioSeedCriteriaTest.$(OBJEXT) \
|
||||||
TimeSeedCriteriaTest.$(OBJEXT)
|
TimeSeedCriteriaTest.$(OBJEXT) SegmentManTest.$(OBJEXT) \
|
||||||
|
SpeedCalcTest.$(OBJEXT)
|
||||||
aria2c_OBJECTS = $(am_aria2c_OBJECTS)
|
aria2c_OBJECTS = $(am_aria2c_OBJECTS)
|
||||||
am__DEPENDENCIES_1 =
|
am__DEPENDENCIES_1 =
|
||||||
aria2c_DEPENDENCIES = ../src/libaria2c.a $(am__DEPENDENCIES_1)
|
aria2c_DEPENDENCIES = ../src/libaria2c.a $(am__DEPENDENCIES_1)
|
||||||
|
@ -267,7 +268,9 @@ aria2c_SOURCES = AllTest.cc\
|
||||||
MetalinkEntryTest.cc\
|
MetalinkEntryTest.cc\
|
||||||
FeatureConfigTest.cc\
|
FeatureConfigTest.cc\
|
||||||
ShareRatioSeedCriteriaTest.cc\
|
ShareRatioSeedCriteriaTest.cc\
|
||||||
TimeSeedCriteriaTest.cc
|
TimeSeedCriteriaTest.cc\
|
||||||
|
SegmentManTest.cc\
|
||||||
|
SpeedCalcTest.cc
|
||||||
|
|
||||||
#aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
|
#aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
|
||||||
#aria2c_LDFLAGS = ${CPPUNIT_LIBS}
|
#aria2c_LDFLAGS = ${CPPUNIT_LIBS}
|
||||||
|
@ -358,8 +361,10 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RejectMessageTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RejectMessageTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestMessageTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestMessageTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestTest.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentManTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShaVisitorTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShaVisitorTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShareRatioSeedCriteriaTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShareRatioSeedCriteriaTest.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SpeedCalcTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SuggestPieceMessageTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SuggestPieceMessageTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeSeedCriteriaTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeSeedCriteriaTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentManTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentManTest.Po@am__quote@
|
||||||
|
|
Loading…
Reference in New Issue