mirror of https://github.com/aria2/aria2
2010-04-08 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added --save-session=FILE option. This option saves error/unfinished downloads to FILE on exit. You can pass this output file to aria2c with -i option on restart. Please note that downloads added by aria2.addTorrent and aria2.addMetalink XML-RPC method are not saved. * src/BtPostDownloadHandler.cc * src/DownloadResult.h * src/Makefile.am * src/MetadataInfo.cc * src/MetadataInfo.h * src/Metalink2RequestGroup.cc * src/MetalinkPostDownloadHandler.cc * src/MultiUrlRequestInfo.cc * src/OptionHandlerFactory.cc * src/RequestGroup.cc * src/RequestGroup.h * src/SessionSerializer.cc * src/SessionSerializer.h * src/UTMetadataPostDownloadHandler.cc * src/download_helper.cc * src/download_helper.h * src/prefs.cc * src/prefs.h * src/usage_text.h * test/Makefile.am * test/SessionSerializerTest.cc * test/XmlRpcMethodTest.cc * test/serialize_session.meta4pull/1/head
parent
dd7590f927
commit
5cd0108f93
31
ChangeLog
31
ChangeLog
|
@ -1,3 +1,34 @@
|
||||||
|
2010-04-08 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||||
|
|
||||||
|
Added --save-session=FILE option. This option saves
|
||||||
|
error/unfinished downloads to FILE on exit. You can pass this
|
||||||
|
output file to aria2c with -i option on restart. Please note that
|
||||||
|
downloads added by aria2.addTorrent and aria2.addMetalink XML-RPC
|
||||||
|
method are not saved.
|
||||||
|
* src/BtPostDownloadHandler.cc
|
||||||
|
* src/DownloadResult.h
|
||||||
|
* src/Makefile.am
|
||||||
|
* src/MetadataInfo.cc
|
||||||
|
* src/MetadataInfo.h
|
||||||
|
* src/Metalink2RequestGroup.cc
|
||||||
|
* src/MetalinkPostDownloadHandler.cc
|
||||||
|
* src/MultiUrlRequestInfo.cc
|
||||||
|
* src/OptionHandlerFactory.cc
|
||||||
|
* src/RequestGroup.cc
|
||||||
|
* src/RequestGroup.h
|
||||||
|
* src/SessionSerializer.cc
|
||||||
|
* src/SessionSerializer.h
|
||||||
|
* src/UTMetadataPostDownloadHandler.cc
|
||||||
|
* src/download_helper.cc
|
||||||
|
* src/download_helper.h
|
||||||
|
* src/prefs.cc
|
||||||
|
* src/prefs.h
|
||||||
|
* src/usage_text.h
|
||||||
|
* test/Makefile.am
|
||||||
|
* test/SessionSerializerTest.cc
|
||||||
|
* test/XmlRpcMethodTest.cc
|
||||||
|
* test/serialize_session.meta4
|
||||||
|
|
||||||
2010-04-07 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
2010-04-07 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||||
|
|
||||||
Fixed the bug that FTP data connection is not established via
|
Fixed the bug that FTP data connection is not established via
|
||||||
|
|
15
doc/aria2c.1
15
doc/aria2c.1
|
@ -2,12 +2,12 @@
|
||||||
.\" Title: aria2c
|
.\" Title: aria2c
|
||||||
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
|
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
|
||||||
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
|
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
|
||||||
.\" Date: 04/03/2010
|
.\" Date: 04/08/2010
|
||||||
.\" Manual: Aria2 Manual
|
.\" Manual: Aria2 Manual
|
||||||
.\" Source: Aria2 1.9.1a
|
.\" Source: Aria2 1.9.1a
|
||||||
.\" Language: English
|
.\" Language: English
|
||||||
.\"
|
.\"
|
||||||
.TH "ARIA2C" "1" "04/03/2010" "Aria2 1\&.9\&.1a" "Aria2 Manual"
|
.TH "ARIA2C" "1" "04/08/2010" "Aria2 1\&.9\&.1a" "Aria2 Manual"
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
.\" * Define some portability stuff
|
.\" * Define some portability stuff
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
|
@ -1354,6 +1354,17 @@ For Metalink downloads, \-C1 is recommended for proxy server which disables resu
|
||||||
.sp .5v
|
.sp .5v
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
|
\fB\-\-save\-session\fR=FILE
|
||||||
|
.RS 4
|
||||||
|
Save error/unfinished downloads to FILE on exit\&. You can pass this output file to aria2c with
|
||||||
|
\fB\-i\fR
|
||||||
|
option on restart\&. Please note that downloads added by
|
||||||
|
\fBaria2\&.addTorrent\fR
|
||||||
|
and
|
||||||
|
\fBaria2\&.addMetalink\fR
|
||||||
|
XML\-RPC method are not saved\&.
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
\fB\-\-stop\fR=SEC
|
\fB\-\-stop\fR=SEC
|
||||||
.RS 4
|
.RS 4
|
||||||
Stop application after SEC seconds has passed\&. If
|
Stop application after SEC seconds has passed\&. If
|
||||||
|
|
|
@ -2201,6 +2201,17 @@ connections.</td>
|
||||||
</div>
|
</div>
|
||||||
<div class="dlist"><dl>
|
<div class="dlist"><dl>
|
||||||
<dt class="hdlist1">
|
<dt class="hdlist1">
|
||||||
|
<strong>--save-session</strong>=FILE
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<p>
|
||||||
|
Save error/unfinished downloads to FILE on exit. You can pass this
|
||||||
|
output file to aria2c with <strong>-i</strong> option on restart. Please note that
|
||||||
|
downloads added by <strong>aria2.addTorrent</strong> and <strong>aria2.addMetalink</strong>
|
||||||
|
XML-RPC method are not saved.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
<dt class="hdlist1">
|
||||||
<strong>--stop</strong>=SEC
|
<strong>--stop</strong>=SEC
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
|
@ -4137,7 +4148,7 @@ files in the program, then also delete it here.</p></div>
|
||||||
<div id="footnotes"><hr /></div>
|
<div id="footnotes"><hr /></div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div id="footer-text">
|
<div id="footer-text">
|
||||||
Last updated 2010-04-03 13:10:23 JST
|
Last updated 2010-04-08 21:48:17 JST
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -914,6 +914,13 @@ For Metalink downloads, -C1 is recommended for proxy server which
|
||||||
disables resume, in order to avoid establishing unnecessary
|
disables resume, in order to avoid establishing unnecessary
|
||||||
connections.
|
connections.
|
||||||
|
|
||||||
|
*--save-session*=FILE::
|
||||||
|
|
||||||
|
Save error/unfinished downloads to FILE on exit. You can pass this
|
||||||
|
output file to aria2c with *-i* option on restart. Please note that
|
||||||
|
downloads added by *aria2.addTorrent* and *aria2.addMetalink*
|
||||||
|
XML-RPC method are not saved.
|
||||||
|
|
||||||
*--stop*=SEC::
|
*--stop*=SEC::
|
||||||
Stop application after SEC seconds has passed.
|
Stop application after SEC seconds has passed.
|
||||||
If '0' is given, this feature is disabled.
|
If '0' is given, this feature is disabled.
|
||||||
|
|
|
@ -82,6 +82,11 @@ void BtPostDownloadHandler::getNextRequestGroups
|
||||||
std::vector<std::string>(),
|
std::vector<std::string>(),
|
||||||
content);
|
content);
|
||||||
requestGroup->followedBy(newRgs.begin(), newRgs.end());
|
requestGroup->followedBy(newRgs.begin(), newRgs.end());
|
||||||
|
SharedHandle<MetadataInfo> mi =
|
||||||
|
createMetadataInfoFromFirstFileEntry(requestGroup->getDownloadContext());
|
||||||
|
if(!mi.isNull()) {
|
||||||
|
setMetadataInfo(newRgs.begin(), newRgs.end(), mi);
|
||||||
|
}
|
||||||
groups.insert(groups.end(), newRgs.begin(), newRgs.end());
|
groups.insert(groups.end(), newRgs.begin(), newRgs.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,8 @@
|
||||||
#include "SharedHandle.h"
|
#include "SharedHandle.h"
|
||||||
#include "DownloadResultCode.h"
|
#include "DownloadResultCode.h"
|
||||||
#include "RequestGroup.h"
|
#include "RequestGroup.h"
|
||||||
|
#include "Option.h"
|
||||||
|
#include "MetadataInfo.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -74,6 +76,10 @@ public:
|
||||||
// RequestGroup.cc::_belongsToGID.
|
// RequestGroup.cc::_belongsToGID.
|
||||||
gid_t belongsTo;
|
gid_t belongsTo;
|
||||||
|
|
||||||
|
SharedHandle<Option> option;
|
||||||
|
|
||||||
|
SharedHandle<MetadataInfo> metadataInfo;
|
||||||
|
|
||||||
DownloadResult(gid_t gid,
|
DownloadResult(gid_t gid,
|
||||||
const std::vector<SharedHandle<FileEntry> >& fileEntries,
|
const std::vector<SharedHandle<FileEntry> >& fileEntries,
|
||||||
bool inMemoryDownload,
|
bool inMemoryDownload,
|
||||||
|
@ -81,7 +87,9 @@ public:
|
||||||
int64_t sessionTime,
|
int64_t sessionTime,
|
||||||
downloadresultcode::RESULT result,
|
downloadresultcode::RESULT result,
|
||||||
const std::vector<gid_t> followedBy,
|
const std::vector<gid_t> followedBy,
|
||||||
gid_t belongsTo):
|
gid_t belongsTo,
|
||||||
|
const SharedHandle<Option>& option,
|
||||||
|
const SharedHandle<MetadataInfo>& metadataInfo):
|
||||||
gid(gid),
|
gid(gid),
|
||||||
fileEntries(fileEntries),
|
fileEntries(fileEntries),
|
||||||
inMemoryDownload(inMemoryDownload),
|
inMemoryDownload(inMemoryDownload),
|
||||||
|
@ -89,7 +97,9 @@ public:
|
||||||
sessionTime(sessionTime),
|
sessionTime(sessionTime),
|
||||||
result(result),
|
result(result),
|
||||||
followedBy(followedBy),
|
followedBy(followedBy),
|
||||||
belongsTo(belongsTo) {}
|
belongsTo(belongsTo),
|
||||||
|
option(option),
|
||||||
|
metadataInfo(metadataInfo) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<DownloadResult> DownloadResultHandle;
|
typedef SharedHandle<DownloadResult> DownloadResultHandle;
|
||||||
|
|
|
@ -198,7 +198,9 @@ SRCS = Socket.h\
|
||||||
CreateRequestCommand.cc CreateRequestCommand.h\
|
CreateRequestCommand.cc CreateRequestCommand.h\
|
||||||
DownloadResultCode.h\
|
DownloadResultCode.h\
|
||||||
wallclock.h\
|
wallclock.h\
|
||||||
download_helper.cc download_helper.h
|
download_helper.cc download_helper.h\
|
||||||
|
MetadataInfo.cc MetadataInfo.h\
|
||||||
|
SessionSerializer.cc SessionSerializer.h
|
||||||
|
|
||||||
if ENABLE_XML_RPC
|
if ENABLE_XML_RPC
|
||||||
SRCS += XmlRpcRequestParserController.cc XmlRpcRequestParserController.h\
|
SRCS += XmlRpcRequestParserController.cc XmlRpcRequestParserController.h\
|
||||||
|
|
|
@ -429,7 +429,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
||||||
LongestSequencePieceSelector.cc LongestSequencePieceSelector.h \
|
LongestSequencePieceSelector.cc LongestSequencePieceSelector.h \
|
||||||
bitfield.cc bitfield.h BDE.cc BDE.h CreateRequestCommand.cc \
|
bitfield.cc bitfield.h BDE.cc BDE.h CreateRequestCommand.cc \
|
||||||
CreateRequestCommand.h DownloadResultCode.h wallclock.h \
|
CreateRequestCommand.h DownloadResultCode.h wallclock.h \
|
||||||
download_helper.cc download_helper.h \
|
download_helper.cc download_helper.h MetadataInfo.cc \
|
||||||
|
MetadataInfo.h SessionSerializer.cc SessionSerializer.h \
|
||||||
XmlRpcRequestParserController.cc \
|
XmlRpcRequestParserController.cc \
|
||||||
XmlRpcRequestParserController.h \
|
XmlRpcRequestParserController.h \
|
||||||
XmlRpcRequestParserStateMachine.cc \
|
XmlRpcRequestParserStateMachine.cc \
|
||||||
|
@ -855,7 +856,8 @@ am__objects_27 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
|
||||||
URIResult.$(OBJEXT) SelectEventPoll.$(OBJEXT) \
|
URIResult.$(OBJEXT) SelectEventPoll.$(OBJEXT) \
|
||||||
LongestSequencePieceSelector.$(OBJEXT) bitfield.$(OBJEXT) \
|
LongestSequencePieceSelector.$(OBJEXT) bitfield.$(OBJEXT) \
|
||||||
BDE.$(OBJEXT) CreateRequestCommand.$(OBJEXT) \
|
BDE.$(OBJEXT) CreateRequestCommand.$(OBJEXT) \
|
||||||
download_helper.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
|
download_helper.$(OBJEXT) MetadataInfo.$(OBJEXT) \
|
||||||
|
SessionSerializer.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
|
||||||
$(am__objects_3) $(am__objects_4) $(am__objects_5) \
|
$(am__objects_3) $(am__objects_4) $(am__objects_5) \
|
||||||
$(am__objects_6) $(am__objects_7) $(am__objects_8) \
|
$(am__objects_6) $(am__objects_7) $(am__objects_8) \
|
||||||
$(am__objects_9) $(am__objects_10) $(am__objects_11) \
|
$(am__objects_9) $(am__objects_10) $(am__objects_11) \
|
||||||
|
@ -1189,16 +1191,17 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \
|
||||||
LongestSequencePieceSelector.cc LongestSequencePieceSelector.h \
|
LongestSequencePieceSelector.cc LongestSequencePieceSelector.h \
|
||||||
bitfield.cc bitfield.h BDE.cc BDE.h CreateRequestCommand.cc \
|
bitfield.cc bitfield.h BDE.cc BDE.h CreateRequestCommand.cc \
|
||||||
CreateRequestCommand.h DownloadResultCode.h wallclock.h \
|
CreateRequestCommand.h DownloadResultCode.h wallclock.h \
|
||||||
download_helper.cc download_helper.h $(am__append_1) \
|
download_helper.cc download_helper.h MetadataInfo.cc \
|
||||||
$(am__append_2) $(am__append_3) $(am__append_4) \
|
MetadataInfo.h SessionSerializer.cc SessionSerializer.h \
|
||||||
$(am__append_5) $(am__append_6) $(am__append_7) \
|
$(am__append_1) $(am__append_2) $(am__append_3) \
|
||||||
$(am__append_8) $(am__append_9) $(am__append_10) \
|
$(am__append_4) $(am__append_5) $(am__append_6) \
|
||||||
$(am__append_11) $(am__append_12) $(am__append_13) \
|
$(am__append_7) $(am__append_8) $(am__append_9) \
|
||||||
$(am__append_14) $(am__append_15) $(am__append_16) \
|
$(am__append_10) $(am__append_11) $(am__append_12) \
|
||||||
$(am__append_17) $(am__append_18) $(am__append_19) \
|
$(am__append_13) $(am__append_14) $(am__append_15) \
|
||||||
$(am__append_20) $(am__append_21) $(am__append_22) \
|
$(am__append_16) $(am__append_17) $(am__append_18) \
|
||||||
$(am__append_23) $(am__append_24) $(am__append_25) \
|
$(am__append_19) $(am__append_20) $(am__append_21) \
|
||||||
$(am__append_26)
|
$(am__append_22) $(am__append_23) $(am__append_24) \
|
||||||
|
$(am__append_25) $(am__append_26)
|
||||||
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@\
|
||||||
|
@ -1495,6 +1498,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MSEHandshake.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MSEHandshake.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MemoryBufferPreDownloadHandler.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MemoryBufferPreDownloadHandler.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MessageDigestHelper.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MessageDigestHelper.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetadataInfo.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Metalink2RequestGroup.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Metalink2RequestGroup.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkEntry.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkEntry.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkHelper.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkHelper.Po@am__quote@
|
||||||
|
@ -1552,6 +1556,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SelectEventPoll.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SelectEventPoll.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerStat.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerStat.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerStatMan.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerStatMan.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SessionSerializer.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Signature.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Signature.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleBtMessage.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleBtMessage.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleLogger.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleLogger.Po@am__quote@
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - The high speed download utility
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give
|
||||||
|
* permission to link the code of portions of this program with the
|
||||||
|
* OpenSSL library under certain conditions as described in each
|
||||||
|
* individual source file, and distribute linked combinations
|
||||||
|
* including the two.
|
||||||
|
* You must obey the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than OpenSSL. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you
|
||||||
|
* do not wish to do so, delete this exception statement from your
|
||||||
|
* version. If you delete this exception statement from all source
|
||||||
|
* files in the program, then also delete it here.
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#include "MetadataInfo.h"
|
||||||
|
|
||||||
|
namespace aria2 {
|
||||||
|
|
||||||
|
int64_t MetadataInfo::_count = 0;
|
||||||
|
|
||||||
|
int64_t MetadataInfo::genId()
|
||||||
|
{
|
||||||
|
if(_count == INT64_MAX) {
|
||||||
|
_count = 0;
|
||||||
|
}
|
||||||
|
return ++_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace aria2
|
|
@ -0,0 +1,76 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - The high speed download utility
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give
|
||||||
|
* permission to link the code of portions of this program with the
|
||||||
|
* OpenSSL library under certain conditions as described in each
|
||||||
|
* individual source file, and distribute linked combinations
|
||||||
|
* including the two.
|
||||||
|
* You must obey the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than OpenSSL. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you
|
||||||
|
* do not wish to do so, delete this exception statement from your
|
||||||
|
* version. If you delete this exception statement from all source
|
||||||
|
* files in the program, then also delete it here.
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#ifndef _D_METADATA_INFO_H_
|
||||||
|
#define _D_METADATA_INFO_H_
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace aria2 {
|
||||||
|
|
||||||
|
class MetadataInfo {
|
||||||
|
private:
|
||||||
|
int64_t _id;
|
||||||
|
std::string _uri;
|
||||||
|
bool _dataOnly;
|
||||||
|
static int64_t _count;
|
||||||
|
public:
|
||||||
|
MetadataInfo(const std::string& uri):_id(genId()), _uri(uri), _dataOnly(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
MetadataInfo():_id(genId()), _dataOnly(true) {}
|
||||||
|
|
||||||
|
bool dataOnly() const
|
||||||
|
{
|
||||||
|
return _dataOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& getUri() const
|
||||||
|
{
|
||||||
|
return _uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t getId() const
|
||||||
|
{
|
||||||
|
return _id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t genId();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace aria2
|
||||||
|
|
||||||
|
#endif // _D_METADATA_INFO_H_
|
|
@ -109,7 +109,16 @@ Metalink2RequestGroup::generate
|
||||||
{
|
{
|
||||||
std::vector<SharedHandle<MetalinkEntry> > entries;
|
std::vector<SharedHandle<MetalinkEntry> > entries;
|
||||||
MetalinkHelper::parseAndQuery(entries, metalinkFile, option.get());
|
MetalinkHelper::parseAndQuery(entries, metalinkFile, option.get());
|
||||||
createRequestGroup(groups, entries, option);
|
std::vector<SharedHandle<RequestGroup> > tempgroups;
|
||||||
|
createRequestGroup(tempgroups, entries, option);
|
||||||
|
SharedHandle<MetadataInfo> mi;
|
||||||
|
if(metalinkFile == "-") {
|
||||||
|
mi.reset(new MetadataInfo());
|
||||||
|
} else {
|
||||||
|
mi.reset(new MetadataInfo(metalinkFile));
|
||||||
|
}
|
||||||
|
setMetadataInfo(tempgroups.begin(), tempgroups.end(), mi);
|
||||||
|
groups.insert(groups.end(), tempgroups.begin(), tempgroups.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -120,7 +129,11 @@ Metalink2RequestGroup::generate
|
||||||
{
|
{
|
||||||
std::vector<SharedHandle<MetalinkEntry> > entries;
|
std::vector<SharedHandle<MetalinkEntry> > entries;
|
||||||
MetalinkHelper::parseAndQuery(entries, binaryStream, option.get());
|
MetalinkHelper::parseAndQuery(entries, binaryStream, option.get());
|
||||||
createRequestGroup(groups, entries, option);
|
std::vector<SharedHandle<RequestGroup> > tempgroups;
|
||||||
|
createRequestGroup(tempgroups, entries, option);
|
||||||
|
SharedHandle<MetadataInfo> mi(new MetadataInfo());
|
||||||
|
setMetadataInfo(tempgroups.begin(), tempgroups.end(), mi);
|
||||||
|
groups.insert(groups.end(), tempgroups.begin(), tempgroups.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "prefs.h"
|
#include "prefs.h"
|
||||||
#include "Option.h"
|
#include "Option.h"
|
||||||
#include "DownloadContext.h"
|
#include "DownloadContext.h"
|
||||||
|
#include "download_helper.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -77,6 +78,11 @@ void MetalinkPostDownloadHandler::getNextRequestGroups
|
||||||
Metalink2RequestGroup().generate(newRgs, diskAdaptor,
|
Metalink2RequestGroup().generate(newRgs, diskAdaptor,
|
||||||
requestGroup->getOption());
|
requestGroup->getOption());
|
||||||
requestGroup->followedBy(newRgs.begin(), newRgs.end());
|
requestGroup->followedBy(newRgs.begin(), newRgs.end());
|
||||||
|
SharedHandle<MetadataInfo> mi =
|
||||||
|
createMetadataInfoFromFirstFileEntry(requestGroup->getDownloadContext());
|
||||||
|
if(!mi.isNull()) {
|
||||||
|
setMetadataInfo(newRgs.begin(), newRgs.end(), mi);
|
||||||
|
}
|
||||||
groups.insert(groups.end(), newRgs.begin(), newRgs.end());
|
groups.insert(groups.end(), newRgs.begin(), newRgs.end());
|
||||||
diskAdaptor->closeFile();
|
diskAdaptor->closeFile();
|
||||||
} catch(Exception& e) {
|
} catch(Exception& e) {
|
||||||
|
|
|
@ -55,6 +55,8 @@
|
||||||
#include "Netrc.h"
|
#include "Netrc.h"
|
||||||
#include "AuthConfigFactory.h"
|
#include "AuthConfigFactory.h"
|
||||||
#include "DownloadContext.h"
|
#include "DownloadContext.h"
|
||||||
|
#include "SessionSerializer.h"
|
||||||
|
#include "ServerStatMan.h"
|
||||||
#ifdef ENABLE_SSL
|
#ifdef ENABLE_SSL
|
||||||
# include "SocketCore.h"
|
# include "SocketCore.h"
|
||||||
# include "TLSContext.h"
|
# include "TLSContext.h"
|
||||||
|
@ -193,6 +195,15 @@ downloadresultcode::RESULT MultiUrlRequestInfo::execute()
|
||||||
returnValue = s.getLastErrorResult();
|
returnValue = s.getLastErrorResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SessionSerializer sessionSerializer(e->_requestGroupMan);
|
||||||
|
// TODO Add option: --save-session-status=error,inprogress,waiting
|
||||||
|
if(!_option->blank(PREF_SAVE_SESSION)) {
|
||||||
|
if(sessionSerializer.save(_option->get(PREF_SAVE_SESSION))) {
|
||||||
|
_logger->notice("Serialized session successfully.");
|
||||||
|
} else {
|
||||||
|
_logger->notice("Failed to serialize session.");
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch(RecoverableException& e) {
|
} catch(RecoverableException& e) {
|
||||||
if(returnValue == downloadresultcode::FINISHED) {
|
if(returnValue == downloadresultcode::FINISHED) {
|
||||||
returnValue = downloadresultcode::UNKNOWN_ERROR;
|
returnValue = downloadresultcode::UNKNOWN_ERROR;
|
||||||
|
|
|
@ -442,6 +442,15 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
|
||||||
op->addTag(TAG_ADVANCED);
|
op->addTag(TAG_ADVANCED);
|
||||||
handlers.push_back(op);
|
handlers.push_back(op);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
SharedHandle<OptionHandler> op(new DefaultOptionHandler
|
||||||
|
(PREF_SAVE_SESSION,
|
||||||
|
TEXT_SAVE_SESSION,
|
||||||
|
NO_DEFAULT_VALUE,
|
||||||
|
"FILENAME"));
|
||||||
|
op->addTag(TAG_ADVANCED);
|
||||||
|
handlers.push_back(op);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
SharedHandle<OptionHandler> op(new NumberOptionHandler
|
SharedHandle<OptionHandler> op(new NumberOptionHandler
|
||||||
(PREF_STOP,
|
(PREF_STOP,
|
||||||
|
|
|
@ -1050,7 +1050,9 @@ DownloadResultHandle RequestGroup::createDownloadResult() const
|
||||||
_downloadContext->calculateSessionTime(),
|
_downloadContext->calculateSessionTime(),
|
||||||
downloadResult(),
|
downloadResult(),
|
||||||
_followedByGIDs,
|
_followedByGIDs,
|
||||||
_belongsToGID));
|
_belongsToGID,
|
||||||
|
_option,
|
||||||
|
_metadataInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestGroup::reportDownloadFinished()
|
void RequestGroup::reportDownloadFinished()
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "TimeA2.h"
|
#include "TimeA2.h"
|
||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
#include "DownloadResultCode.h"
|
#include "DownloadResultCode.h"
|
||||||
|
#include "MetadataInfo.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -165,6 +166,8 @@ private:
|
||||||
// RequestGroup.
|
// RequestGroup.
|
||||||
gid_t _belongsToGID;
|
gid_t _belongsToGID;
|
||||||
|
|
||||||
|
SharedHandle<MetadataInfo> _metadataInfo;
|
||||||
|
|
||||||
RequestGroupMan* _requestGroupMan;
|
RequestGroupMan* _requestGroupMan;
|
||||||
|
|
||||||
int _resumeFailureCount;
|
int _resumeFailureCount;
|
||||||
|
@ -514,6 +517,16 @@ public:
|
||||||
|
|
||||||
bool p2pInvolved() const;
|
bool p2pInvolved() const;
|
||||||
|
|
||||||
|
void setMetadataInfo(const SharedHandle<MetadataInfo>& info)
|
||||||
|
{
|
||||||
|
_metadataInfo = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SharedHandle<MetadataInfo>& getMetadataInfo() const
|
||||||
|
{
|
||||||
|
return _metadataInfo;
|
||||||
|
}
|
||||||
|
|
||||||
static void resetGIDCounter() { _gidCounter = 0; }
|
static void resetGIDCounter() { _gidCounter = 0; }
|
||||||
|
|
||||||
static gid_t newGID();
|
static gid_t newGID();
|
||||||
|
|
|
@ -0,0 +1,203 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - The high speed download utility
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give
|
||||||
|
* permission to link the code of portions of this program with the
|
||||||
|
* OpenSSL library under certain conditions as described in each
|
||||||
|
* individual source file, and distribute linked combinations
|
||||||
|
* including the two.
|
||||||
|
* You must obey the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than OpenSSL. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you
|
||||||
|
* do not wish to do so, delete this exception statement from your
|
||||||
|
* version. If you delete this exception statement from all source
|
||||||
|
* files in the program, then also delete it here.
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#include "SessionSerializer.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
#include "RequestGroupMan.h"
|
||||||
|
#include "ServerStatMan.h"
|
||||||
|
#include "a2functional.h"
|
||||||
|
#include "File.h"
|
||||||
|
#include "A2STR.h"
|
||||||
|
#include "download_helper.h"
|
||||||
|
#include "Option.h"
|
||||||
|
#include "DownloadResult.h"
|
||||||
|
#include "FileEntry.h"
|
||||||
|
#include "prefs.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "array_fun.h"
|
||||||
|
|
||||||
|
namespace aria2 {
|
||||||
|
|
||||||
|
SessionSerializer::SessionSerializer
|
||||||
|
(const SharedHandle<RequestGroupMan>& requestGroupMan):
|
||||||
|
_rgman(requestGroupMan),
|
||||||
|
_saveError(true),
|
||||||
|
_saveInProgress(true),
|
||||||
|
_saveWaiting(true) {}
|
||||||
|
|
||||||
|
bool SessionSerializer::save(const std::string& filename) const
|
||||||
|
{
|
||||||
|
std::string tempFilename = strconcat(filename, "__temp");
|
||||||
|
std::ofstream out(tempFilename.c_str(), std::ios::binary);
|
||||||
|
if(!out) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
save(out);
|
||||||
|
out.flush();
|
||||||
|
if(!out) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return File(tempFilename).renameTo(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const std::vector<std::string>& getCumulativeOpts()
|
||||||
|
{
|
||||||
|
static std::string cumulativeOpts[] = { PREF_INDEX_OUT, PREF_HEADER };
|
||||||
|
static std::vector<std::string> opts
|
||||||
|
(vbegin(cumulativeOpts), vend(cumulativeOpts));
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool inCumulativeOpts(const std::string& opt)
|
||||||
|
{
|
||||||
|
const std::vector<std::string>& cumopts = getCumulativeOpts();
|
||||||
|
for(std::vector<std::string>::const_iterator itr = cumopts.begin(),
|
||||||
|
eoi = cumopts.end(); itr != eoi; ++itr) {
|
||||||
|
if(opt == *itr) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeOption(std::ostream& out, const SharedHandle<Option>& op)
|
||||||
|
{
|
||||||
|
const std::set<std::string>& requestOptions = listRequestOptions();
|
||||||
|
for(std::set<std::string>::const_iterator itr = requestOptions.begin(),
|
||||||
|
eoi = requestOptions.end(); itr != eoi; ++itr) {
|
||||||
|
if(inCumulativeOpts(*itr)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(op->defined(*itr)) {
|
||||||
|
out << " " << *itr << "=" << op->get(*itr) << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const std::vector<std::string>& cumopts = getCumulativeOpts();
|
||||||
|
for(std::vector<std::string>::const_iterator opitr = cumopts.begin(),
|
||||||
|
eoi = cumopts.end(); opitr != eoi; ++opitr) {
|
||||||
|
if(op->defined(*opitr)) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
util::split(op->get(*opitr), std::back_inserter(v), "\n",
|
||||||
|
false, false);
|
||||||
|
for(std::vector<std::string>::const_iterator i = v.begin(), eoi = v.end();
|
||||||
|
i != eoi; ++i) {
|
||||||
|
out << " " << *opitr << "=" << *i << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeDownloadResult
|
||||||
|
(std::ostream& out, std::set<int64_t>& metainfoCache,
|
||||||
|
const SharedHandle<DownloadResult>& dr)
|
||||||
|
{
|
||||||
|
const SharedHandle<MetadataInfo>& mi = dr->metadataInfo;
|
||||||
|
if(dr->belongsTo != 0 || (!mi.isNull() && mi->dataOnly())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(mi.isNull()) {
|
||||||
|
// only save first file entry
|
||||||
|
if(dr->fileEntries.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const SharedHandle<FileEntry>& file = dr->fileEntries[0];
|
||||||
|
std::vector<std::string> uris;
|
||||||
|
file->getUris(uris);
|
||||||
|
if(uris.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::copy(uris.begin(), uris.end(),
|
||||||
|
std::ostream_iterator<std::string>(out, "\t"));
|
||||||
|
out << "\n";
|
||||||
|
} else {
|
||||||
|
if(metainfoCache.count(mi->getId()) != 0) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
metainfoCache.insert(mi->getId());
|
||||||
|
out << mi->getUri() << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeOption(out, dr->option);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionSerializer::save(std::ostream& out) const
|
||||||
|
{
|
||||||
|
std::set<int64_t> metainfoCache;
|
||||||
|
const std::deque<SharedHandle<DownloadResult> >& results =
|
||||||
|
_rgman->getDownloadResults();
|
||||||
|
for(std::deque<SharedHandle<DownloadResult> >::const_iterator itr =
|
||||||
|
results.begin(), eoi = results.end(); itr != eoi; ++itr) {
|
||||||
|
if((*itr)->result == downloadresultcode::FINISHED) {
|
||||||
|
continue;
|
||||||
|
} else if((*itr)->result == downloadresultcode::IN_PROGRESS) {
|
||||||
|
if(_saveInProgress) {
|
||||||
|
writeDownloadResult(out, metainfoCache, *itr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// error download
|
||||||
|
if(_saveError) {
|
||||||
|
writeDownloadResult(out, metainfoCache, *itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(_saveInProgress) {
|
||||||
|
const std::deque<SharedHandle<RequestGroup> >& groups =
|
||||||
|
_rgman->getRequestGroups();
|
||||||
|
for(std::deque<SharedHandle<RequestGroup> >::const_iterator itr =
|
||||||
|
groups.begin(), eoi = groups.end(); itr != eoi; ++itr) {
|
||||||
|
SharedHandle<DownloadResult> result = (*itr)->createDownloadResult();
|
||||||
|
if(result->result == downloadresultcode::FINISHED) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
writeDownloadResult(out, metainfoCache, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(_saveWaiting) {
|
||||||
|
const std::deque<SharedHandle<RequestGroup> >& groups =
|
||||||
|
_rgman->getReservedGroups();
|
||||||
|
for(std::deque<SharedHandle<RequestGroup> >::const_iterator itr =
|
||||||
|
groups.begin(), eoi = groups.end(); itr != eoi; ++itr) {
|
||||||
|
SharedHandle<DownloadResult> result = (*itr)->createDownloadResult();
|
||||||
|
writeDownloadResult(out, metainfoCache, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace aria2
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - The high speed download utility
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give
|
||||||
|
* permission to link the code of portions of this program with the
|
||||||
|
* OpenSSL library under certain conditions as described in each
|
||||||
|
* individual source file, and distribute linked combinations
|
||||||
|
* including the two.
|
||||||
|
* You must obey the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than OpenSSL. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you
|
||||||
|
* do not wish to do so, delete this exception statement from your
|
||||||
|
* version. If you delete this exception statement from all source
|
||||||
|
* files in the program, then also delete it here.
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#ifndef _D_SESSION_SERIALIZER_H_
|
||||||
|
#define _D_SESSION_SERIALIZER_H_
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <iosfwd>
|
||||||
|
|
||||||
|
#include "SharedHandle.h"
|
||||||
|
|
||||||
|
namespace aria2 {
|
||||||
|
|
||||||
|
class RequestGroupMan;
|
||||||
|
|
||||||
|
class SessionSerializer {
|
||||||
|
private:
|
||||||
|
SharedHandle<RequestGroupMan> _rgman;
|
||||||
|
bool _saveError;
|
||||||
|
bool _saveInProgress;
|
||||||
|
bool _saveWaiting;
|
||||||
|
public:
|
||||||
|
SessionSerializer(const SharedHandle<RequestGroupMan>& requestGroupMan);
|
||||||
|
|
||||||
|
bool save(const std::string& filename) const;
|
||||||
|
|
||||||
|
void save(std::ostream& out) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace aria2
|
||||||
|
|
||||||
|
#endif // _D_SESSION_SERIALIZER_H_
|
|
@ -96,8 +96,11 @@ void UTMetadataPostDownloadHandler::getNextRequestGroups
|
||||||
std::vector<SharedHandle<RequestGroup> > newRgs;
|
std::vector<SharedHandle<RequestGroup> > newRgs;
|
||||||
createRequestGroupForBitTorrent(newRgs, requestGroup->getOption(),
|
createRequestGroupForBitTorrent(newRgs, requestGroup->getOption(),
|
||||||
std::vector<std::string>(), torrent);
|
std::vector<std::string>(), torrent);
|
||||||
|
|
||||||
requestGroup->followedBy(newRgs.begin(), newRgs.end());
|
requestGroup->followedBy(newRgs.begin(), newRgs.end());
|
||||||
|
if(!requestGroup->getMetadataInfo().isNull()) {
|
||||||
|
setMetadataInfo(newRgs.begin(), newRgs.end(),
|
||||||
|
requestGroup->getMetadataInfo());
|
||||||
|
}
|
||||||
groups.insert(groups.end(), newRgs.begin(), newRgs.end());
|
groups.insert(groups.end(), newRgs.begin(), newRgs.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
#include "ByteArrayDiskWriter.h"
|
#include "ByteArrayDiskWriter.h"
|
||||||
#include "a2functional.h"
|
#include "a2functional.h"
|
||||||
#include "ByteArrayDiskWriterFactory.h"
|
#include "ByteArrayDiskWriterFactory.h"
|
||||||
|
#include "MetadataInfo.h"
|
||||||
#ifdef ENABLE_BITTORRENT
|
#ifdef ENABLE_BITTORRENT
|
||||||
# include "bittorrent_helper.h"
|
# include "bittorrent_helper.h"
|
||||||
# include "BtConstants.h"
|
# include "BtConstants.h"
|
||||||
|
@ -212,6 +213,16 @@ static SharedHandle<RequestGroup> createRequestGroup
|
||||||
return rg;
|
return rg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SharedHandle<MetadataInfo> createMetadataInfo(const std::string& uri)
|
||||||
|
{
|
||||||
|
return SharedHandle<MetadataInfo>(new MetadataInfo(uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
static SharedHandle<MetadataInfo> createMetadataInfoDataOnly()
|
||||||
|
{
|
||||||
|
return SharedHandle<MetadataInfo>(new MetadataInfo());
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_BITTORRENT
|
#ifdef ENABLE_BITTORRENT
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -226,10 +237,12 @@ createBtRequestGroup(const std::string& torrentFilePath,
|
||||||
dctx->setDir(option->get(PREF_DIR));
|
dctx->setDir(option->get(PREF_DIR));
|
||||||
if(torrentData.empty()) {
|
if(torrentData.empty()) {
|
||||||
bittorrent::load(torrentFilePath, dctx, auxUris);// may throw exception
|
bittorrent::load(torrentFilePath, dctx, auxUris);// may throw exception
|
||||||
|
rg->setMetadataInfo(createMetadataInfo(torrentFilePath));
|
||||||
} else {
|
} else {
|
||||||
bittorrent::loadFromMemory(torrentData, dctx, auxUris, "default"); // may
|
bittorrent::loadFromMemory(torrentData, dctx, auxUris, "default"); // may
|
||||||
// throw
|
// throw
|
||||||
// exception
|
// exception
|
||||||
|
rg->setMetadataInfo(createMetadataInfoDataOnly());
|
||||||
}
|
}
|
||||||
dctx->setFileFilter(util::parseIntRange(option->get(PREF_SELECT_FILE)));
|
dctx->setFileFilter(util::parseIntRange(option->get(PREF_SELECT_FILE)));
|
||||||
std::istringstream indexOutIn(option->get(PREF_INDEX_OUT));
|
std::istringstream indexOutIn(option->get(PREF_INDEX_OUT));
|
||||||
|
@ -272,6 +285,7 @@ createBtMagnetRequestGroup(const std::string& magnetLink,
|
||||||
(new UTMetadataPostDownloadHandler()));
|
(new UTMetadataPostDownloadHandler()));
|
||||||
rg->setDiskWriterFactory
|
rg->setDiskWriterFactory
|
||||||
(SharedHandle<DiskWriterFactory>(new ByteArrayDiskWriterFactory()));
|
(SharedHandle<DiskWriterFactory>(new ByteArrayDiskWriterFactory()));
|
||||||
|
rg->setMetadataInfo(createMetadataInfo(magnetLink));
|
||||||
return rg;
|
return rg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,4 +490,19 @@ void createRequestGroupForUriList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SharedHandle<MetadataInfo>
|
||||||
|
createMetadataInfoFromFirstFileEntry(const SharedHandle<DownloadContext>& dctx)
|
||||||
|
{
|
||||||
|
if(dctx->getFileEntries().empty()) {
|
||||||
|
return SharedHandle<MetadataInfo>();
|
||||||
|
} else {
|
||||||
|
std::vector<std::string> uris;
|
||||||
|
dctx->getFileEntries()[0]->getUris(uris);
|
||||||
|
if(uris.empty()) {
|
||||||
|
return SharedHandle<MetadataInfo>();
|
||||||
|
}
|
||||||
|
return SharedHandle<MetadataInfo>(new MetadataInfo(uris[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -47,6 +47,8 @@ namespace aria2 {
|
||||||
|
|
||||||
class RequestGroup;
|
class RequestGroup;
|
||||||
class Option;
|
class Option;
|
||||||
|
class MetadataInfo;
|
||||||
|
class DownloadContext;
|
||||||
|
|
||||||
const std::set<std::string>& listRequestOptions();
|
const std::set<std::string>& listRequestOptions();
|
||||||
|
|
||||||
|
@ -90,6 +92,18 @@ void createRequestGroupForUri
|
||||||
bool ignoreForceSequential = false,
|
bool ignoreForceSequential = false,
|
||||||
bool ignoreLocalPath = false);
|
bool ignoreLocalPath = false);
|
||||||
|
|
||||||
|
template<typename InputIterator>
|
||||||
|
void setMetadataInfo
|
||||||
|
(InputIterator first, InputIterator last, const SharedHandle<MetadataInfo>& mi)
|
||||||
|
{
|
||||||
|
for(; first != last; ++first) {
|
||||||
|
(*first)->setMetadataInfo(mi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedHandle<MetadataInfo>
|
||||||
|
createMetadataInfoFromFirstFileEntry(const SharedHandle<DownloadContext>& dctx);
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
||||||
#endif // _D_DOWNLOAD_HELPER_H_
|
#endif // _D_DOWNLOAD_HELPER_H_
|
||||||
|
|
|
@ -184,8 +184,8 @@ const std::string PREF_REMOVE_CONTROL_FILE("remove-control-file");
|
||||||
const std::string PREF_ALWAYS_RESUME("always-resume");
|
const std::string PREF_ALWAYS_RESUME("always-resume");
|
||||||
// value: 1*digit
|
// value: 1*digit
|
||||||
const std::string PREF_MAX_RESUME_FAILURE_TRIES("max-resume-failure-tries");
|
const std::string PREF_MAX_RESUME_FAILURE_TRIES("max-resume-failure-tries");
|
||||||
// value: true | false
|
// value: string that your file system recognizes as a file name.
|
||||||
const std::string PREF_HTTP_ACCEPT_GZIP("http-accept-gzip");
|
const std::string PREF_SAVE_SESSION("save-session");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FTP related preferences
|
* FTP related preferences
|
||||||
|
@ -234,6 +234,8 @@ const std::string PREF_USE_HEAD("use-head");
|
||||||
const std::string PREF_HTTP_AUTH_CHALLENGE("http-auth-challenge");
|
const std::string PREF_HTTP_AUTH_CHALLENGE("http-auth-challenge");
|
||||||
// value: true | false
|
// value: true | false
|
||||||
const std::string PREF_HTTP_NO_CACHE("http-no-cache");
|
const std::string PREF_HTTP_NO_CACHE("http-no-cache");
|
||||||
|
// value: true | false
|
||||||
|
const std::string PREF_HTTP_ACCEPT_GZIP("http-accept-gzip");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Proxy related preferences
|
* Proxy related preferences
|
||||||
|
|
|
@ -188,8 +188,8 @@ extern const std::string PREF_REMOVE_CONTROL_FILE;
|
||||||
extern const std::string PREF_ALWAYS_RESUME;
|
extern const std::string PREF_ALWAYS_RESUME;
|
||||||
// value: 1*digit
|
// value: 1*digit
|
||||||
extern const std::string PREF_MAX_RESUME_FAILURE_TRIES;
|
extern const std::string PREF_MAX_RESUME_FAILURE_TRIES;
|
||||||
// value: true | false
|
// value: string that your file system recognizes as a file name.
|
||||||
extern const std::string PREF_HTTP_ACCEPT_GZIP;
|
extern const std::string PREF_SAVE_SESSION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FTP related preferences
|
* FTP related preferences
|
||||||
|
@ -238,6 +238,8 @@ extern const std::string PREF_USE_HEAD;
|
||||||
extern const std::string PREF_HTTP_AUTH_CHALLENGE;
|
extern const std::string PREF_HTTP_AUTH_CHALLENGE;
|
||||||
// value: true | false
|
// value: true | false
|
||||||
extern const std::string PREF_HTTP_NO_CACHE;
|
extern const std::string PREF_HTTP_NO_CACHE;
|
||||||
|
// value: true | false
|
||||||
|
extern const std::string PREF_HTTP_ACCEPT_GZIP;
|
||||||
|
|
||||||
/**;
|
/**;
|
||||||
* Proxy related preferences
|
* Proxy related preferences
|
||||||
|
|
|
@ -672,3 +672,9 @@
|
||||||
" and inflate response if remote server responds\n" \
|
" and inflate response if remote server responds\n" \
|
||||||
" with 'Content-Encoding: gzip' or\n" \
|
" with 'Content-Encoding: gzip' or\n" \
|
||||||
" 'Content-Encoding: deflate'.")
|
" 'Content-Encoding: deflate'.")
|
||||||
|
#define TEXT_SAVE_SESSION \
|
||||||
|
_(" --save-session=FILE Save error/unfinished downloads to FILE on exit.\n" \
|
||||||
|
" You can pass this output file to aria2c with -i\n" \
|
||||||
|
" option on restart. Please note that downloads\n" \
|
||||||
|
" added by aria2.addTorrent and aria2.addMetalink\n" \
|
||||||
|
" XML-RPC method are not saved.")
|
||||||
|
|
|
@ -71,7 +71,8 @@ aria2c_SOURCES = AllTest.cc\
|
||||||
a2algoTest.cc\
|
a2algoTest.cc\
|
||||||
bitfieldTest.cc\
|
bitfieldTest.cc\
|
||||||
BDETest.cc\
|
BDETest.cc\
|
||||||
DownloadContextTest.cc
|
DownloadContextTest.cc\
|
||||||
|
SessionSerializerTest.cc
|
||||||
|
|
||||||
if ENABLE_XML_RPC
|
if ENABLE_XML_RPC
|
||||||
aria2c_SOURCES += XmlRpcRequestParserControllerTest.cc\
|
aria2c_SOURCES += XmlRpcRequestParserControllerTest.cc\
|
||||||
|
|
|
@ -213,7 +213,8 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
|
||||||
RarestPieceSelectorTest.cc PieceStatManTest.cc \
|
RarestPieceSelectorTest.cc PieceStatManTest.cc \
|
||||||
InOrderPieceSelector.h LongestSequencePieceSelectorTest.cc \
|
InOrderPieceSelector.h LongestSequencePieceSelectorTest.cc \
|
||||||
a2algoTest.cc bitfieldTest.cc BDETest.cc \
|
a2algoTest.cc bitfieldTest.cc BDETest.cc \
|
||||||
DownloadContextTest.cc XmlRpcRequestParserControllerTest.cc \
|
DownloadContextTest.cc SessionSerializerTest.cc \
|
||||||
|
XmlRpcRequestParserControllerTest.cc \
|
||||||
XmlRpcRequestProcessorTest.cc XmlRpcMethodTest.cc \
|
XmlRpcRequestProcessorTest.cc XmlRpcMethodTest.cc \
|
||||||
FallocFileAllocationIteratorTest.cc GZipDecoderTest.cc \
|
FallocFileAllocationIteratorTest.cc GZipDecoderTest.cc \
|
||||||
GZipEncoderTest.cc Sqlite3MozCookieParserTest.cc \
|
GZipEncoderTest.cc Sqlite3MozCookieParserTest.cc \
|
||||||
|
@ -406,9 +407,10 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) TestUtil.$(OBJEXT) \
|
||||||
RarestPieceSelectorTest.$(OBJEXT) PieceStatManTest.$(OBJEXT) \
|
RarestPieceSelectorTest.$(OBJEXT) PieceStatManTest.$(OBJEXT) \
|
||||||
LongestSequencePieceSelectorTest.$(OBJEXT) \
|
LongestSequencePieceSelectorTest.$(OBJEXT) \
|
||||||
a2algoTest.$(OBJEXT) bitfieldTest.$(OBJEXT) BDETest.$(OBJEXT) \
|
a2algoTest.$(OBJEXT) bitfieldTest.$(OBJEXT) BDETest.$(OBJEXT) \
|
||||||
DownloadContextTest.$(OBJEXT) $(am__objects_1) \
|
DownloadContextTest.$(OBJEXT) SessionSerializerTest.$(OBJEXT) \
|
||||||
$(am__objects_2) $(am__objects_3) $(am__objects_4) \
|
$(am__objects_1) $(am__objects_2) $(am__objects_3) \
|
||||||
$(am__objects_5) $(am__objects_6) $(am__objects_7)
|
$(am__objects_4) $(am__objects_5) $(am__objects_6) \
|
||||||
|
$(am__objects_7)
|
||||||
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)
|
||||||
|
@ -639,9 +641,10 @@ aria2c_SOURCES = AllTest.cc TestUtil.cc TestUtil.h SocketCoreTest.cc \
|
||||||
RarestPieceSelectorTest.cc PieceStatManTest.cc \
|
RarestPieceSelectorTest.cc PieceStatManTest.cc \
|
||||||
InOrderPieceSelector.h LongestSequencePieceSelectorTest.cc \
|
InOrderPieceSelector.h LongestSequencePieceSelectorTest.cc \
|
||||||
a2algoTest.cc bitfieldTest.cc BDETest.cc \
|
a2algoTest.cc bitfieldTest.cc BDETest.cc \
|
||||||
DownloadContextTest.cc $(am__append_1) $(am__append_2) \
|
DownloadContextTest.cc SessionSerializerTest.cc \
|
||||||
$(am__append_3) $(am__append_4) $(am__append_5) \
|
$(am__append_1) $(am__append_2) $(am__append_3) \
|
||||||
$(am__append_6) $(am__append_7)
|
$(am__append_4) $(am__append_5) $(am__append_6) \
|
||||||
|
$(am__append_7)
|
||||||
|
|
||||||
#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}
|
||||||
|
@ -870,6 +873,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SequentialPickerTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SequentialPickerTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerStatManTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerStatManTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerStatTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerStatTest.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SessionSerializerTest.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)/SharedHandleTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SharedHandleTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SignatureTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SignatureTest.Po@am__quote@
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
#include "SessionSerializer.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
|
||||||
|
#include "RequestGroupMan.h"
|
||||||
|
#include "ServerStatMan.h"
|
||||||
|
#include "array_fun.h"
|
||||||
|
#include "download_helper.h"
|
||||||
|
#include "FileEntry.h"
|
||||||
|
#include "prefs.h"
|
||||||
|
|
||||||
|
namespace aria2 {
|
||||||
|
|
||||||
|
class SessionSerializerTest:public CppUnit::TestFixture {
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE(SessionSerializerTest);
|
||||||
|
CPPUNIT_TEST(testSave);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
public:
|
||||||
|
void testSave();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(SessionSerializerTest);
|
||||||
|
|
||||||
|
void SessionSerializerTest::testSave()
|
||||||
|
{
|
||||||
|
#if defined(ENABLE_BITTORRENT) && defined(ENABLE_METALINK)
|
||||||
|
const std::string URIs[] =
|
||||||
|
{ "http://localhost/file",
|
||||||
|
"http://mirror/file",
|
||||||
|
"test.torrent",
|
||||||
|
"serialize_session.meta4",
|
||||||
|
"magnet:?xt=urn:btih:248D0A1CD08284299DE78D5C1ED359BB46717D8C"};
|
||||||
|
std::vector<std::string> uris(vbegin(URIs), vend(URIs));
|
||||||
|
std::vector<SharedHandle<RequestGroup> > result;
|
||||||
|
SharedHandle<Option> option(new Option());
|
||||||
|
option->put(PREF_DIR, "/tmp");
|
||||||
|
createRequestGroupForUri(result, option, uris);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)5, result.size());
|
||||||
|
SharedHandle<RequestGroupMan> rgman
|
||||||
|
(new RequestGroupMan(result, 1, option.get()));
|
||||||
|
SessionSerializer s(rgman);
|
||||||
|
std::stringstream ss;
|
||||||
|
s.save(ss);
|
||||||
|
std::string line;
|
||||||
|
std::getline(ss, line);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(strconcat(uris[0], "\t", uris[1], "\t"), line);
|
||||||
|
std::getline(ss, line);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string(" dir=/tmp"), line);
|
||||||
|
std::getline(ss, line);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(uris[2], line);
|
||||||
|
std::getline(ss, line);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string(" dir=/tmp"), line);
|
||||||
|
std::getline(ss, line);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(uris[3], line);
|
||||||
|
std::getline(ss, line);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string(" dir=/tmp"), line);
|
||||||
|
std::getline(ss, line);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(uris[4], line);
|
||||||
|
std::getline(ss, line);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string(" dir=/tmp"), line);
|
||||||
|
std::getline(ss, line);
|
||||||
|
CPPUNIT_ASSERT(!ss);
|
||||||
|
#endif // defined(ENABLE_BITTORRENT) && defined(ENABLE_METALINK)
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace aria2
|
|
@ -679,7 +679,9 @@ void XmlRpcMethodTest::testGatherStoppedDownload()
|
||||||
1000,
|
1000,
|
||||||
downloadresultcode::FINISHED,
|
downloadresultcode::FINISHED,
|
||||||
followedBy,
|
followedBy,
|
||||||
2));
|
2,
|
||||||
|
SharedHandle<Option>(),
|
||||||
|
SharedHandle<MetadataInfo>()));
|
||||||
BDE entry = BDE::dict();
|
BDE entry = BDE::dict();
|
||||||
gatherStoppedDownload(entry, d);
|
gatherStoppedDownload(entry, d);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<metalink xmlns="urn:ietf:params:xml:ns:metalink">
|
||||||
|
<file name="t/README">
|
||||||
|
<url>http://example.org/README</url>
|
||||||
|
</file>
|
||||||
|
<file name="t/image.iso">
|
||||||
|
<url>http://example.org/image.iso</url>
|
||||||
|
</file>
|
||||||
|
</metalink>
|
Loading…
Reference in New Issue