mirror of https://github.com/aria2/aria2
2008-05-11 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Pass std::deque<Command*> by reference to avoid unnecessary coping. * src/AbstractCommand.cc * src/BtCheckIntegrityEntry.cc * src/BtCheckIntegrityEntry.h * src/BtFileAllocationEntry.cc * src/BtFileAllocationEntry.h * src/BtSetup.cc * src/BtSetup.h * src/CheckIntegrityCommand.cc * src/CheckIntegrityEntry.h * src/ChecksumCheckIntegrityEntry.cc * src/ChecksumCheckIntegrityEntry.h * src/DHTSetup.cc * src/DHTSetup.h * src/DownloadEngine.cc * src/FileAllocationCommand.cc * src/FileAllocationEntry.h * src/RequestGroup.cc * src/RequestGroup.h * src/RequestGroupMan.cc * src/RequestGroupMan.h * src/StreamCheckIntegrityEntry.cc * src/StreamCheckIntegrityEntry.h * src/StreamFileAllocationEntry.cc * src/StreamFileAllocationEntry.h * src/TrackerWatcherCommand.cc * src/a2functional.hpull/1/head
parent
6d78a7656d
commit
825cfe7715
30
ChangeLog
30
ChangeLog
|
@ -1,3 +1,33 @@
|
||||||
|
2008-05-11 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
|
Pass std::deque<Command*> by reference to avoid unnecessary coping.
|
||||||
|
* src/AbstractCommand.cc
|
||||||
|
* src/BtCheckIntegrityEntry.cc
|
||||||
|
* src/BtCheckIntegrityEntry.h
|
||||||
|
* src/BtFileAllocationEntry.cc
|
||||||
|
* src/BtFileAllocationEntry.h
|
||||||
|
* src/BtSetup.cc
|
||||||
|
* src/BtSetup.h
|
||||||
|
* src/CheckIntegrityCommand.cc
|
||||||
|
* src/CheckIntegrityEntry.h
|
||||||
|
* src/ChecksumCheckIntegrityEntry.cc
|
||||||
|
* src/ChecksumCheckIntegrityEntry.h
|
||||||
|
* src/DHTSetup.cc
|
||||||
|
* src/DHTSetup.h
|
||||||
|
* src/DownloadEngine.cc
|
||||||
|
* src/FileAllocationCommand.cc
|
||||||
|
* src/FileAllocationEntry.h
|
||||||
|
* src/RequestGroup.cc
|
||||||
|
* src/RequestGroup.h
|
||||||
|
* src/RequestGroupMan.cc
|
||||||
|
* src/RequestGroupMan.h
|
||||||
|
* src/StreamCheckIntegrityEntry.cc
|
||||||
|
* src/StreamCheckIntegrityEntry.h
|
||||||
|
* src/StreamFileAllocationEntry.cc
|
||||||
|
* src/StreamFileAllocationEntry.h
|
||||||
|
* src/TrackerWatcherCommand.cc
|
||||||
|
* src/a2functional.h
|
||||||
|
|
||||||
2008-05-11 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
2008-05-11 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
Changed method signature:
|
Changed method signature:
|
||||||
|
|
|
@ -184,7 +184,8 @@ bool AbstractCommand::execute() {
|
||||||
|
|
||||||
void AbstractCommand::tryReserved() {
|
void AbstractCommand::tryReserved() {
|
||||||
_requestGroup->removeServerHost(cuid);
|
_requestGroup->removeServerHost(cuid);
|
||||||
Commands commands = _requestGroup->createNextCommand(e, 1);
|
Commands commands;
|
||||||
|
_requestGroup->createNextCommand(commands, e, 1);
|
||||||
e->addCommand(commands);
|
e->addCommand(commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +324,11 @@ bool AbstractCommand::nameResolveFinished() const {
|
||||||
void AbstractCommand::prepareForNextAction(Command* nextCommand)
|
void AbstractCommand::prepareForNextAction(Command* nextCommand)
|
||||||
{
|
{
|
||||||
CheckIntegrityEntryHandle entry(new StreamCheckIntegrityEntry(req, _requestGroup, nextCommand));
|
CheckIntegrityEntryHandle entry(new StreamCheckIntegrityEntry(req, _requestGroup, nextCommand));
|
||||||
e->addCommand(_requestGroup->processCheckIntegrityEntry(entry, e));
|
|
||||||
|
std::deque<Command*> commands;
|
||||||
|
_requestGroup->processCheckIntegrityEntry(commands, entry, e);
|
||||||
|
|
||||||
|
e->addCommand(commands);
|
||||||
e->setNoWait(true);
|
e->setNoWait(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,26 +47,26 @@ BtCheckIntegrityEntry::BtCheckIntegrityEntry(RequestGroup* requestGroup):
|
||||||
|
|
||||||
BtCheckIntegrityEntry::~BtCheckIntegrityEntry() {}
|
BtCheckIntegrityEntry::~BtCheckIntegrityEntry() {}
|
||||||
|
|
||||||
Commands BtCheckIntegrityEntry::onDownloadIncomplete(DownloadEngine* e)
|
void BtCheckIntegrityEntry::onDownloadIncomplete(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e)
|
||||||
{
|
{
|
||||||
Commands commands;
|
|
||||||
FileAllocationEntryHandle entry(new BtFileAllocationEntry(_requestGroup));
|
FileAllocationEntryHandle entry(new BtFileAllocationEntry(_requestGroup));
|
||||||
if(_requestGroup->needsFileAllocation()) {
|
if(_requestGroup->needsFileAllocation()) {
|
||||||
e->_fileAllocationMan->pushFileAllocationEntry(entry);
|
e->_fileAllocationMan->pushFileAllocationEntry(entry);
|
||||||
} else {
|
} else {
|
||||||
commands = entry->prepareForNextAction(e);
|
entry->prepareForNextAction(commands, e);
|
||||||
}
|
}
|
||||||
return commands;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands BtCheckIntegrityEntry::onDownloadFinished(DownloadEngine* e)
|
void BtCheckIntegrityEntry::onDownloadFinished(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e)
|
||||||
{
|
{
|
||||||
_requestGroup->getPieceStorage()->getDiskAdaptor()->onDownloadComplete();
|
_requestGroup->getPieceStorage()->getDiskAdaptor()->onDownloadComplete();
|
||||||
// TODO Currently,when all the checksums
|
// TODO Currently,when all the checksums
|
||||||
// are valid, then aira2 goes to seeding mode. Sometimes it is better
|
// are valid, then aira2 goes to seeding mode. Sometimes it is better
|
||||||
// to exit rather than doing seeding. So, it would be good to toggle this
|
// to exit rather than doing seeding. So, it would be good to toggle this
|
||||||
// behavior.
|
// behavior.
|
||||||
return onDownloadIncomplete(e);
|
onDownloadIncomplete(commands, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -45,9 +45,11 @@ public:
|
||||||
|
|
||||||
virtual ~BtCheckIntegrityEntry();
|
virtual ~BtCheckIntegrityEntry();
|
||||||
|
|
||||||
virtual std::deque<Command*> onDownloadFinished(DownloadEngine* e);
|
virtual void onDownloadFinished(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e);
|
||||||
|
|
||||||
virtual std::deque<Command*> onDownloadIncomplete(DownloadEngine* e);
|
virtual void onDownloadIncomplete(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<BtCheckIntegrityEntry> BtCheckIntegrityEntryHandle;
|
typedef SharedHandle<BtCheckIntegrityEntry> BtCheckIntegrityEntryHandle;
|
||||||
|
|
|
@ -46,14 +46,13 @@ BtFileAllocationEntry::BtFileAllocationEntry(RequestGroup* requestGroup):
|
||||||
|
|
||||||
BtFileAllocationEntry::~BtFileAllocationEntry() {}
|
BtFileAllocationEntry::~BtFileAllocationEntry() {}
|
||||||
|
|
||||||
Commands BtFileAllocationEntry::prepareForNextAction(DownloadEngine* e)
|
void BtFileAllocationEntry::prepareForNextAction(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e)
|
||||||
{
|
{
|
||||||
Commands commands = BtSetup().setup(_requestGroup, e, e->option);
|
BtSetup().setup(commands, _requestGroup, e, e->option);
|
||||||
if(!_requestGroup->downloadFinished()) {
|
if(!_requestGroup->downloadFinished()) {
|
||||||
Commands streamCommands = _requestGroup->createNextCommandWithAdj(e, 0);
|
_requestGroup->createNextCommandWithAdj(commands, e, 0);
|
||||||
std::copy(streamCommands.begin(), streamCommands.end(), std::back_inserter(commands));
|
|
||||||
}
|
}
|
||||||
return commands;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -45,7 +45,8 @@ public:
|
||||||
|
|
||||||
virtual ~BtFileAllocationEntry();
|
virtual ~BtFileAllocationEntry();
|
||||||
|
|
||||||
virtual std::deque<Command*> prepareForNextAction(DownloadEngine* e);
|
virtual void prepareForNextAction(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<BtFileAllocationEntry> BtFileAllocationEntryHandle;
|
typedef SharedHandle<BtFileAllocationEntry> BtFileAllocationEntryHandle;
|
||||||
|
|
|
@ -61,14 +61,14 @@ namespace aria2 {
|
||||||
|
|
||||||
BtSetup::BtSetup():_logger(LogFactory::getInstance()) {}
|
BtSetup::BtSetup():_logger(LogFactory::getInstance()) {}
|
||||||
|
|
||||||
Commands BtSetup::setup(RequestGroup* requestGroup,
|
void BtSetup::setup(std::deque<Command*>& commands,
|
||||||
|
RequestGroup* requestGroup,
|
||||||
DownloadEngine* e,
|
DownloadEngine* e,
|
||||||
const Option* option)
|
const Option* option)
|
||||||
{
|
{
|
||||||
Commands commands;
|
|
||||||
BtContextHandle btContext(dynamic_pointer_cast<BtContext>(requestGroup->getDownloadContext()));
|
BtContextHandle btContext(dynamic_pointer_cast<BtContext>(requestGroup->getDownloadContext()));
|
||||||
if(btContext.isNull()) {
|
if(btContext.isNull()) {
|
||||||
return commands;
|
return;
|
||||||
}
|
}
|
||||||
// commands
|
// commands
|
||||||
commands.push_back(new TrackerWatcherCommand(CUIDCounterSingletonHolder::instance()->newID(),
|
commands.push_back(new TrackerWatcherCommand(CUIDCounterSingletonHolder::instance()->newID(),
|
||||||
|
@ -126,7 +126,6 @@ Commands BtSetup::setup(RequestGroup* requestGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
BT_RUNTIME(btContext)->setReady(true);
|
BT_RUNTIME(btContext)->setReady(true);
|
||||||
return commands;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -52,7 +52,8 @@ private:
|
||||||
public:
|
public:
|
||||||
BtSetup();
|
BtSetup();
|
||||||
|
|
||||||
std::deque<Command*> setup(RequestGroup* requestGroup,
|
void setup(std::deque<Command*>& commands,
|
||||||
|
RequestGroup* requestGroup,
|
||||||
DownloadEngine* e,
|
DownloadEngine* e,
|
||||||
const Option* option);
|
const Option* option);
|
||||||
};
|
};
|
||||||
|
|
|
@ -65,11 +65,15 @@ bool CheckIntegrityCommand::executeInternal()
|
||||||
if(_requestGroup->downloadFinished()) {
|
if(_requestGroup->downloadFinished()) {
|
||||||
logger->notice(MSG_VERIFICATION_SUCCESSFUL,
|
logger->notice(MSG_VERIFICATION_SUCCESSFUL,
|
||||||
_requestGroup->getFilePath().c_str());
|
_requestGroup->getFilePath().c_str());
|
||||||
_e->addCommand(_entry->onDownloadFinished(_e));
|
std::deque<Command*> commands;
|
||||||
|
_entry->onDownloadFinished(commands, _e);
|
||||||
|
_e->addCommand(commands);
|
||||||
} else {
|
} else {
|
||||||
logger->error(MSG_VERIFICATION_FAILED,
|
logger->error(MSG_VERIFICATION_FAILED,
|
||||||
_requestGroup->getFilePath().c_str());
|
_requestGroup->getFilePath().c_str());
|
||||||
_e->addCommand(_entry->onDownloadIncomplete(_e));
|
std::deque<Command*> commands;
|
||||||
|
_entry->onDownloadIncomplete(commands,_e);
|
||||||
|
_e->addCommand(commands);
|
||||||
}
|
}
|
||||||
_e->setNoWait(true);
|
_e->setNoWait(true);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -65,9 +65,11 @@ public:
|
||||||
|
|
||||||
virtual void initValidator() = 0;
|
virtual void initValidator() = 0;
|
||||||
|
|
||||||
virtual std::deque<Command*> onDownloadFinished(DownloadEngine* e) = 0;
|
virtual void onDownloadFinished(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e) = 0;
|
||||||
|
|
||||||
virtual std::deque<Command*> onDownloadIncomplete(DownloadEngine* e) = 0;
|
virtual void onDownloadIncomplete(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
|
typedef SharedHandle<CheckIntegrityEntry> CheckIntegrityEntryHandle;
|
||||||
|
|
|
@ -64,16 +64,14 @@ void ChecksumCheckIntegrityEntry::initValidator()
|
||||||
_validator->init();
|
_validator->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::deque<Command*>
|
void
|
||||||
ChecksumCheckIntegrityEntry::onDownloadFinished(DownloadEngine* e)
|
ChecksumCheckIntegrityEntry::onDownloadFinished(std::deque<Command*>& commands,
|
||||||
{
|
DownloadEngine* e)
|
||||||
return std::deque<Command*>();
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
std::deque<Command*>
|
void
|
||||||
ChecksumCheckIntegrityEntry::onDownloadIncomplete(DownloadEngine* e)
|
ChecksumCheckIntegrityEntry::onDownloadIncomplete(std::deque<Command*>& commands,
|
||||||
{
|
DownloadEngine* e)
|
||||||
return std::deque<Command*>();
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -50,9 +50,11 @@ public:
|
||||||
|
|
||||||
virtual void initValidator();
|
virtual void initValidator();
|
||||||
|
|
||||||
virtual std::deque<Command*> onDownloadFinished(DownloadEngine* e);
|
virtual void onDownloadFinished(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e);
|
||||||
|
|
||||||
virtual std::deque<Command*> onDownloadIncomplete(DownloadEngine* e);
|
virtual void onDownloadIncomplete(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -65,7 +65,9 @@
|
||||||
#include "SocketCore.h"
|
#include "SocketCore.h"
|
||||||
#include "DlAbortEx.h"
|
#include "DlAbortEx.h"
|
||||||
#include "RecoverableException.h"
|
#include "RecoverableException.h"
|
||||||
|
#include "a2functional.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -75,11 +77,13 @@ DHTSetup::DHTSetup():_logger(LogFactory::getInstance()) {}
|
||||||
|
|
||||||
DHTSetup::~DHTSetup() {}
|
DHTSetup::~DHTSetup() {}
|
||||||
|
|
||||||
Commands DHTSetup::setup(DownloadEngine* e, const Option* option)
|
void DHTSetup::setup(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e, const Option* option)
|
||||||
{
|
{
|
||||||
if(_initialized) {
|
if(_initialized) {
|
||||||
return Commands();
|
return;
|
||||||
}
|
}
|
||||||
|
std::deque<Command*> tempCommands;
|
||||||
try {
|
try {
|
||||||
// load routing table and localnode id here
|
// load routing table and localnode id here
|
||||||
|
|
||||||
|
@ -182,7 +186,6 @@ Commands DHTSetup::setup(DownloadEngine* e, const Option* option)
|
||||||
taskQueue->addPeriodicTask1(task);
|
taskQueue->addPeriodicTask1(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands commands;
|
|
||||||
if(!option->get(PREF_DHT_ENTRY_POINT_HOST).empty()) {
|
if(!option->get(PREF_DHT_ENTRY_POINT_HOST).empty()) {
|
||||||
{
|
{
|
||||||
std::pair<std::string, uint16_t> addr(option->get(PREF_DHT_ENTRY_POINT_HOST),
|
std::pair<std::string, uint16_t> addr(option->get(PREF_DHT_ENTRY_POINT_HOST),
|
||||||
|
@ -195,7 +198,7 @@ Commands DHTSetup::setup(DownloadEngine* e, const Option* option)
|
||||||
command->setTaskFactory(taskFactory);
|
command->setTaskFactory(taskFactory);
|
||||||
command->setRoutingTable(routingTable);
|
command->setRoutingTable(routingTable);
|
||||||
command->setLocalNode(localNode);
|
command->setLocalNode(localNode);
|
||||||
commands.push_back(command);
|
tempCommands.push_back(command);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_logger->info("No DHT entry point specified.");
|
_logger->info("No DHT entry point specified.");
|
||||||
|
@ -206,38 +209,37 @@ Commands DHTSetup::setup(DownloadEngine* e, const Option* option)
|
||||||
command->setMessageReceiver(receiver);
|
command->setMessageReceiver(receiver);
|
||||||
command->setTaskQueue(taskQueue);
|
command->setTaskQueue(taskQueue);
|
||||||
command->setReadCheckSocket(connection->getSocket());
|
command->setReadCheckSocket(connection->getSocket());
|
||||||
commands.push_back(command);
|
tempCommands.push_back(command);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
DHTTokenUpdateCommand* command = new DHTTokenUpdateCommand(CUIDCounterSingletonHolder::instance()->newID(), e, DHT_TOKEN_UPDATE_INTERVAL);
|
DHTTokenUpdateCommand* command = new DHTTokenUpdateCommand(CUIDCounterSingletonHolder::instance()->newID(), e, DHT_TOKEN_UPDATE_INTERVAL);
|
||||||
command->setTokenTracker(tokenTracker);
|
command->setTokenTracker(tokenTracker);
|
||||||
commands.push_back(command);
|
tempCommands.push_back(command);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
DHTBucketRefreshCommand* command = new DHTBucketRefreshCommand(CUIDCounterSingletonHolder::instance()->newID(), e, DHT_BUCKET_REFRESH_CHECK_INTERVAL);
|
DHTBucketRefreshCommand* command = new DHTBucketRefreshCommand(CUIDCounterSingletonHolder::instance()->newID(), e, DHT_BUCKET_REFRESH_CHECK_INTERVAL);
|
||||||
command->setTaskQueue(taskQueue);
|
command->setTaskQueue(taskQueue);
|
||||||
command->setRoutingTable(routingTable);
|
command->setRoutingTable(routingTable);
|
||||||
command->setTaskFactory(taskFactory);
|
command->setTaskFactory(taskFactory);
|
||||||
commands.push_back(command);
|
tempCommands.push_back(command);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
DHTPeerAnnounceCommand* command = new DHTPeerAnnounceCommand(CUIDCounterSingletonHolder::instance()->newID(), e, DHT_PEER_ANNOUNCE_CHECK_INTERVAL);
|
DHTPeerAnnounceCommand* command = new DHTPeerAnnounceCommand(CUIDCounterSingletonHolder::instance()->newID(), e, DHT_PEER_ANNOUNCE_CHECK_INTERVAL);
|
||||||
command->setPeerAnnounceStorage(peerAnnounceStorage);
|
command->setPeerAnnounceStorage(peerAnnounceStorage);
|
||||||
commands.push_back(command);
|
tempCommands.push_back(command);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
DHTAutoSaveCommand* command = new DHTAutoSaveCommand(CUIDCounterSingletonHolder::instance()->newID(), e, 30*60);
|
DHTAutoSaveCommand* command = new DHTAutoSaveCommand(CUIDCounterSingletonHolder::instance()->newID(), e, 30*60);
|
||||||
command->setLocalNode(localNode);
|
command->setLocalNode(localNode);
|
||||||
command->setRoutingTable(routingTable);
|
command->setRoutingTable(routingTable);
|
||||||
commands.push_back(command);
|
tempCommands.push_back(command);
|
||||||
}
|
}
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
|
commands.insert(commands.end(), tempCommands.begin(), tempCommands.end());
|
||||||
return commands;
|
|
||||||
} catch(RecoverableException& e) {
|
} catch(RecoverableException& e) {
|
||||||
_logger->error("Exception caught while initializing DHT functionality. DHT is disabled.", e);
|
_logger->error("Exception caught while initializing DHT functionality. DHT is disabled.", e);
|
||||||
DHTRegistry::clear();
|
DHTRegistry::clear();
|
||||||
return Commands();
|
std::for_each(tempCommands.begin(), tempCommands.end(), Deleter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,8 @@ public:
|
||||||
|
|
||||||
~DHTSetup();
|
~DHTSetup();
|
||||||
|
|
||||||
std::deque<Command*> setup(DownloadEngine* e, const Option* option);
|
void setup(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e, const Option* option);
|
||||||
|
|
||||||
static bool initialized();
|
static bool initialized();
|
||||||
};
|
};
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "a2time.h"
|
#include "a2time.h"
|
||||||
#include "Socket.h"
|
#include "Socket.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
#include "a2functional.h"
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -96,14 +97,6 @@ DownloadEngine::~DownloadEngine() {
|
||||||
cleanQueue();
|
cleanQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
class Deleter {
|
|
||||||
public:
|
|
||||||
template<class T>
|
|
||||||
void operator()(T* ptr) {
|
|
||||||
delete ptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void DownloadEngine::cleanQueue() {
|
void DownloadEngine::cleanQueue() {
|
||||||
std::for_each(commands.begin(), commands.end(), Deleter());
|
std::for_each(commands.begin(), commands.end(), Deleter());
|
||||||
commands.clear();
|
commands.clear();
|
||||||
|
@ -311,7 +304,9 @@ void DownloadEngine::requestHalt()
|
||||||
|
|
||||||
void DownloadEngine::fillCommand()
|
void DownloadEngine::fillCommand()
|
||||||
{
|
{
|
||||||
addCommand(_requestGroupMan->getInitialCommands(this));
|
std::deque<Command*> commands;
|
||||||
|
_requestGroupMan->getInitialCommands(commands, this);
|
||||||
|
addCommand(commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadEngine::setStatCalc(const StatCalcHandle& statCalc)
|
void DownloadEngine::setStatCalc(const StatCalcHandle& statCalc)
|
||||||
|
|
|
@ -62,7 +62,9 @@ bool FileAllocationCommand::executeInternal()
|
||||||
Util::itos(_requestGroup->getTotalLength(), true).c_str());
|
Util::itos(_requestGroup->getTotalLength(), true).c_str());
|
||||||
_e->_fileAllocationMan->markCurrentFileAllocationEntryDone();
|
_e->_fileAllocationMan->markCurrentFileAllocationEntryDone();
|
||||||
|
|
||||||
_e->addCommand(_fileAllocationEntry->prepareForNextAction(_e));
|
std::deque<Command*> commands;
|
||||||
|
_fileAllocationEntry->prepareForNextAction(commands, _e);
|
||||||
|
_e->addCommand(commands);
|
||||||
_e->setNoWait(true);
|
_e->setNoWait(true);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -61,7 +61,8 @@ public:
|
||||||
|
|
||||||
void allocateChunk();
|
void allocateChunk();
|
||||||
|
|
||||||
virtual std::deque<Command*> prepareForNextAction(DownloadEngine* e) = 0;
|
virtual void prepareForNextAction(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;
|
typedef SharedHandle<FileAllocationEntry> FileAllocationEntryHandle;
|
||||||
|
|
|
@ -171,7 +171,8 @@ void RequestGroup::closeFile()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands RequestGroup::createInitialCommand(DownloadEngine* e)
|
void RequestGroup::createInitialCommand(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_BITTORRENT
|
#ifdef ENABLE_BITTORRENT
|
||||||
{
|
{
|
||||||
|
@ -253,7 +254,9 @@ Commands RequestGroup::createInitialCommand(DownloadEngine* e)
|
||||||
_progressInfoFile = progressInfoFile;
|
_progressInfoFile = progressInfoFile;
|
||||||
|
|
||||||
if(!btContext->isPrivate() && _option->getAsBool(PREF_ENABLE_DHT)) {
|
if(!btContext->isPrivate() && _option->getAsBool(PREF_ENABLE_DHT)) {
|
||||||
e->addCommand(DHTSetup().setup(e, _option));
|
std::deque<Command*> commands;
|
||||||
|
DHTSetup().setup(commands, e, _option);
|
||||||
|
e->addCommand(commands);
|
||||||
if(btContext->getNodes().size() && DHTSetup::initialized()) {
|
if(btContext->getNodes().size() && DHTSetup::initialized()) {
|
||||||
DHTEntryPointNameResolveCommand* command =
|
DHTEntryPointNameResolveCommand* command =
|
||||||
new DHTEntryPointNameResolveCommand(CUIDCounterSingletonHolder::instance()->newID(), e, btContext->getNodes());
|
new DHTEntryPointNameResolveCommand(CUIDCounterSingletonHolder::instance()->newID(), e, btContext->getNodes());
|
||||||
|
@ -266,14 +269,15 @@ Commands RequestGroup::createInitialCommand(DownloadEngine* e)
|
||||||
}
|
}
|
||||||
CheckIntegrityEntryHandle entry(new BtCheckIntegrityEntry(this));
|
CheckIntegrityEntryHandle entry(new BtCheckIntegrityEntry(this));
|
||||||
|
|
||||||
return processCheckIntegrityEntry(entry, e);
|
processCheckIntegrityEntry(commands, entry, e);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // ENABLE_BITTORRENT
|
#endif // ENABLE_BITTORRENT
|
||||||
// TODO I assume here when totallength is set to DownloadContext and it is
|
// TODO I assume here when totallength is set to DownloadContext and it is
|
||||||
// not 0, then filepath is also set DownloadContext correctly....
|
// not 0, then filepath is also set DownloadContext correctly....
|
||||||
if(_downloadContext->getTotalLength() == 0) {
|
if(_downloadContext->getTotalLength() == 0) {
|
||||||
return createNextCommand(e, 1);
|
createNextCommand(commands, e, 1);
|
||||||
}else {
|
}else {
|
||||||
if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) {
|
if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) {
|
||||||
throw DownloadFailureException
|
throw DownloadFailureException
|
||||||
|
@ -281,19 +285,20 @@ Commands RequestGroup::createInitialCommand(DownloadEngine* e)
|
||||||
getFilePath().c_str()).str());
|
getFilePath().c_str()).str());
|
||||||
}
|
}
|
||||||
initPieceStorage();
|
initPieceStorage();
|
||||||
BtProgressInfoFileHandle
|
BtProgressInfoFileHandle infoFile
|
||||||
infoFile(new DefaultBtProgressInfoFile(_downloadContext, _pieceStorage, _option));
|
(new DefaultBtProgressInfoFile(_downloadContext, _pieceStorage, _option));
|
||||||
if(!infoFile->exists() && downloadFinishedByFileLength()) {
|
if(infoFile->exists() || !downloadFinishedByFileLength()) {
|
||||||
return Commands();
|
|
||||||
}
|
|
||||||
loadAndOpenFile(infoFile);
|
loadAndOpenFile(infoFile);
|
||||||
SharedHandle<CheckIntegrityEntry>
|
SharedHandle<CheckIntegrityEntry> checkIntegrityEntry
|
||||||
checkIntegrityEntry(new StreamCheckIntegrityEntry(SharedHandle<Request>(), this));
|
(new StreamCheckIntegrityEntry(SharedHandle<Request>(), this));
|
||||||
return processCheckIntegrityEntry(checkIntegrityEntry, e);
|
processCheckIntegrityEntry(commands, checkIntegrityEntry, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands RequestGroup::processCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry, DownloadEngine* e)
|
void RequestGroup::processCheckIntegrityEntry(std::deque<Command*>& commands,
|
||||||
|
const CheckIntegrityEntryHandle& entry,
|
||||||
|
DownloadEngine* e)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_MESSAGE_DIGEST
|
#ifdef ENABLE_MESSAGE_DIGEST
|
||||||
if(e->option->get(PREF_CHECK_INTEGRITY) == V_TRUE &&
|
if(e->option->get(PREF_CHECK_INTEGRITY) == V_TRUE &&
|
||||||
|
@ -301,13 +306,11 @@ Commands RequestGroup::processCheckIntegrityEntry(const CheckIntegrityEntryHandl
|
||||||
entry->initValidator();
|
entry->initValidator();
|
||||||
CheckIntegrityCommand* command =
|
CheckIntegrityCommand* command =
|
||||||
new CheckIntegrityCommand(CUIDCounterSingletonHolder::instance()->newID(), this, e, entry);
|
new CheckIntegrityCommand(CUIDCounterSingletonHolder::instance()->newID(), this, e, entry);
|
||||||
Commands commands;
|
|
||||||
commands.push_back(command);
|
commands.push_back(command);
|
||||||
return commands;
|
|
||||||
} else
|
} else
|
||||||
#endif // ENABLE_MESSAGE_DIGEST
|
#endif // ENABLE_MESSAGE_DIGEST
|
||||||
{
|
{
|
||||||
return entry->onDownloadIncomplete(e);
|
entry->onDownloadIncomplete(commands, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,25 +461,28 @@ bool RequestGroup::tryAutoFileRenaming()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands RequestGroup::createNextCommandWithAdj(DownloadEngine* e, int numAdj)
|
void RequestGroup::createNextCommandWithAdj(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e, int numAdj)
|
||||||
{
|
{
|
||||||
unsigned int numCommand;
|
unsigned int numCommand;
|
||||||
if(_numConcurrentCommand == 0) {
|
if(_numConcurrentCommand == 0) {
|
||||||
numCommand = _uris.size();
|
numCommand = _uris.size();
|
||||||
} else {
|
} else {
|
||||||
int n = _numConcurrentCommand+numAdj;
|
int n = _numConcurrentCommand+numAdj;
|
||||||
if(n <= 0) {
|
if(n > 0) {
|
||||||
return Commands();
|
|
||||||
} else {
|
|
||||||
numCommand = n;
|
numCommand = n;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return createNextCommand(e, numCommand, "GET");
|
createNextCommand(commands, e, numCommand, "GET");
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands RequestGroup::createNextCommand(DownloadEngine* e, unsigned int numCommand, const std::string& method)
|
void RequestGroup::createNextCommand(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e,
|
||||||
|
unsigned int numCommand,
|
||||||
|
const std::string& method)
|
||||||
{
|
{
|
||||||
Commands commands;
|
|
||||||
std::deque<std::string> pendingURIs;
|
std::deque<std::string> pendingURIs;
|
||||||
for(;!_uris.empty() && numCommand--; _uris.pop_front()) {
|
for(;!_uris.empty() && numCommand--; _uris.pop_front()) {
|
||||||
std::string uri = _uris.front();
|
std::string uri = _uris.front();
|
||||||
|
@ -505,7 +511,6 @@ Commands RequestGroup::createNextCommand(DownloadEngine* e, unsigned int numComm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::copy(pendingURIs.begin(), pendingURIs.end(), std::front_inserter(_uris));
|
std::copy(pendingURIs.begin(), pendingURIs.end(), std::front_inserter(_uris));
|
||||||
return commands;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RequestGroup::getFilePath() const
|
std::string RequestGroup::getFilePath() const
|
||||||
|
|
|
@ -140,11 +140,15 @@ public:
|
||||||
|
|
||||||
SharedHandle<SegmentMan> getSegmentMan() const;
|
SharedHandle<SegmentMan> getSegmentMan() const;
|
||||||
|
|
||||||
std::deque<Command*> createInitialCommand(DownloadEngine* e);
|
void createInitialCommand(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e);
|
||||||
|
|
||||||
std::deque<Command*> createNextCommandWithAdj(DownloadEngine* e, int numAdj);
|
void createNextCommandWithAdj(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e, int numAdj);
|
||||||
|
|
||||||
std::deque<Command*> createNextCommand(DownloadEngine* e, unsigned int numCommand, const std::string& method = "GET");
|
void createNextCommand(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e, unsigned int numCommand,
|
||||||
|
const std::string& method = "GET");
|
||||||
|
|
||||||
void addURI(const std::string& uri)
|
void addURI(const std::string& uri)
|
||||||
{
|
{
|
||||||
|
@ -291,8 +295,8 @@ public:
|
||||||
|
|
||||||
void clearPreDowloadHandler();
|
void clearPreDowloadHandler();
|
||||||
|
|
||||||
std::deque<Command*>
|
void processCheckIntegrityEntry(std::deque<Command*>& commands,
|
||||||
processCheckIntegrityEntry(const SharedHandle<CheckIntegrityEntry>& entry,
|
const SharedHandle<CheckIntegrityEntry>& entry,
|
||||||
DownloadEngine* e);
|
DownloadEngine* e);
|
||||||
|
|
||||||
void initPieceStorage();
|
void initPieceStorage();
|
||||||
|
|
|
@ -153,7 +153,8 @@ void RequestGroupMan::fillRequestGroupFromReserver(DownloadEngine* e)
|
||||||
temp.push_front(groupToAdd);
|
temp.push_front(groupToAdd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Commands commands = groupToAdd->createInitialCommand(e);
|
Commands commands;
|
||||||
|
groupToAdd->createInitialCommand(commands, e);
|
||||||
_requestGroups.push_back(groupToAdd);
|
_requestGroups.push_back(groupToAdd);
|
||||||
++count;
|
++count;
|
||||||
e->addCommand(commands);
|
e->addCommand(commands);
|
||||||
|
@ -169,15 +170,14 @@ void RequestGroupMan::fillRequestGroupFromReserver(DownloadEngine* e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands RequestGroupMan::getInitialCommands(DownloadEngine* e)
|
void RequestGroupMan::getInitialCommands(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e)
|
||||||
{
|
{
|
||||||
Commands commands;
|
|
||||||
for(RequestGroups::iterator itr = _requestGroups.begin();
|
for(RequestGroups::iterator itr = _requestGroups.begin();
|
||||||
itr != _requestGroups.end();) {
|
itr != _requestGroups.end();) {
|
||||||
try {
|
try {
|
||||||
if((*itr)->isDependencyResolved()) {
|
if((*itr)->isDependencyResolved()) {
|
||||||
Commands nextCommands = (*itr)->createInitialCommand(e);
|
(*itr)->createInitialCommand(commands, e);
|
||||||
std::copy(nextCommands.begin(), nextCommands.end(), std::back_inserter(commands));
|
|
||||||
++itr;
|
++itr;
|
||||||
} else {
|
} else {
|
||||||
_reservedGroups.push_front((*itr));
|
_reservedGroups.push_front((*itr));
|
||||||
|
@ -189,7 +189,6 @@ Commands RequestGroupMan::getInitialCommands(DownloadEngine* e)
|
||||||
itr = _requestGroups.erase(itr);
|
itr = _requestGroups.erase(itr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return commands;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestGroupMan::save()
|
void RequestGroupMan::save()
|
||||||
|
|
|
@ -77,7 +77,7 @@ public:
|
||||||
|
|
||||||
void forceHalt();
|
void forceHalt();
|
||||||
|
|
||||||
std::deque<Command*> getInitialCommands(DownloadEngine* e);
|
void getInitialCommands(std::deque<Command*>& commands, DownloadEngine* e);
|
||||||
|
|
||||||
void removeStoppedGroup();
|
void removeStoppedGroup();
|
||||||
|
|
||||||
|
|
|
@ -50,23 +50,21 @@ StreamCheckIntegrityEntry::StreamCheckIntegrityEntry(const RequestHandle& curren
|
||||||
|
|
||||||
StreamCheckIntegrityEntry::~StreamCheckIntegrityEntry() {}
|
StreamCheckIntegrityEntry::~StreamCheckIntegrityEntry() {}
|
||||||
|
|
||||||
Commands StreamCheckIntegrityEntry::onDownloadIncomplete(DownloadEngine* e)
|
void StreamCheckIntegrityEntry::onDownloadIncomplete(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e)
|
||||||
{
|
{
|
||||||
Commands commands;
|
|
||||||
FileAllocationEntryHandle entry
|
FileAllocationEntryHandle entry
|
||||||
(new StreamFileAllocationEntry(_currentRequest, _requestGroup,
|
(new StreamFileAllocationEntry(_currentRequest, _requestGroup,
|
||||||
popNextCommand()));
|
popNextCommand()));
|
||||||
if(_requestGroup->needsFileAllocation()) {
|
if(_requestGroup->needsFileAllocation()) {
|
||||||
e->_fileAllocationMan->pushFileAllocationEntry(entry);
|
e->_fileAllocationMan->pushFileAllocationEntry(entry);
|
||||||
} else {
|
} else {
|
||||||
commands = entry->prepareForNextAction(e);
|
entry->prepareForNextAction(commands, e);
|
||||||
}
|
}
|
||||||
return commands;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands StreamCheckIntegrityEntry::onDownloadFinished(DownloadEngine* e)
|
void StreamCheckIntegrityEntry::onDownloadFinished(std::deque<Command*>& commands,
|
||||||
{
|
DownloadEngine* e)
|
||||||
return Commands();
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -54,9 +54,11 @@ public:
|
||||||
|
|
||||||
virtual ~StreamCheckIntegrityEntry();
|
virtual ~StreamCheckIntegrityEntry();
|
||||||
|
|
||||||
virtual std::deque<Command*> onDownloadFinished(DownloadEngine* e);
|
virtual void onDownloadFinished(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e);
|
||||||
|
|
||||||
virtual std::deque<Command*> onDownloadIncomplete(DownloadEngine* e);
|
virtual void onDownloadIncomplete(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<StreamCheckIntegrityEntry> StreamCheckIntegrityEntryHandle;
|
typedef SharedHandle<StreamCheckIntegrityEntry> StreamCheckIntegrityEntryHandle;
|
||||||
|
|
|
@ -53,29 +53,29 @@ StreamFileAllocationEntry::StreamFileAllocationEntry(const RequestHandle& curren
|
||||||
|
|
||||||
StreamFileAllocationEntry::~StreamFileAllocationEntry() {}
|
StreamFileAllocationEntry::~StreamFileAllocationEntry() {}
|
||||||
|
|
||||||
Commands StreamFileAllocationEntry::prepareForNextAction(DownloadEngine* e)
|
void StreamFileAllocationEntry::prepareForNextAction(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e)
|
||||||
{
|
{
|
||||||
Commands commands;
|
|
||||||
if(_nextCommand) {
|
if(_nextCommand) {
|
||||||
// give _nextCommand a chance to execute in the next execution loop.
|
// give _nextCommand a chance to execute in the next execution loop.
|
||||||
_nextCommand->setStatus(Command::STATUS_ONESHOT_REALTIME);
|
_nextCommand->setStatus(Command::STATUS_ONESHOT_REALTIME);
|
||||||
commands.push_back(popNextCommand());
|
commands.push_back(popNextCommand());
|
||||||
// try remaining uris
|
// try remaining uris
|
||||||
Commands streamCommands = _requestGroup->createNextCommandWithAdj(e, -1);
|
_requestGroup->createNextCommandWithAdj(commands, e, -1);
|
||||||
std::copy(streamCommands.begin(), streamCommands.end(), std::back_inserter(commands));
|
|
||||||
} else {
|
} else {
|
||||||
if(_currentRequest.isNull()) {
|
if(_currentRequest.isNull()) {
|
||||||
commands = _requestGroup->createNextCommandWithAdj(e, 0);
|
_requestGroup->createNextCommandWithAdj(commands, e, 0);
|
||||||
} else {
|
} else {
|
||||||
Commands streamCommands = _requestGroup->createNextCommandWithAdj(e, -1);
|
Command* command =
|
||||||
Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(),
|
InitiateConnectionCommandFactory::createInitiateConnectionCommand
|
||||||
|
(CUIDCounterSingletonHolder::instance()->newID(),
|
||||||
_currentRequest, _requestGroup, e);
|
_currentRequest, _requestGroup, e);
|
||||||
|
|
||||||
commands.push_back(command);
|
commands.push_back(command);
|
||||||
std::copy(streamCommands.begin(), streamCommands.end(), std::back_inserter(commands));
|
|
||||||
|
_requestGroup->createNextCommandWithAdj(commands, e, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return commands;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -53,7 +53,8 @@ public:
|
||||||
|
|
||||||
virtual ~StreamFileAllocationEntry();
|
virtual ~StreamFileAllocationEntry();
|
||||||
|
|
||||||
virtual std::deque<Command*> prepareForNextAction(DownloadEngine* e);
|
virtual void prepareForNextAction(std::deque<Command*>& commands,
|
||||||
|
DownloadEngine* e);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedHandle<StreamFileAllocationEntry> StreamFileAllocationEntryHandle;
|
typedef SharedHandle<StreamFileAllocationEntry> StreamFileAllocationEntryHandle;
|
||||||
|
|
|
@ -88,7 +88,9 @@ bool TrackerWatcherCommand::execute() {
|
||||||
if(_trackerRequestGroup.isNull()) {
|
if(_trackerRequestGroup.isNull()) {
|
||||||
_trackerRequestGroup = createAnnounce();
|
_trackerRequestGroup = createAnnounce();
|
||||||
if(!_trackerRequestGroup.isNull()) {
|
if(!_trackerRequestGroup.isNull()) {
|
||||||
e->addCommand(_trackerRequestGroup->createInitialCommand(e));
|
std::deque<Command*> commands;
|
||||||
|
_trackerRequestGroup->createInitialCommand(commands, e);
|
||||||
|
e->addCommand(commands);
|
||||||
logger->debug("added tracker request command");
|
logger->debug("added tracker request command");
|
||||||
}
|
}
|
||||||
} else if(_trackerRequestGroup->downloadFinished()){
|
} else if(_trackerRequestGroup->downloadFinished()){
|
||||||
|
|
|
@ -151,6 +151,14 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Deleter {
|
||||||
|
public:
|
||||||
|
template<class T>
|
||||||
|
void operator()(T* ptr) {
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
||||||
#endif // _D_A2_FUNCTIONAL_H_
|
#endif // _D_A2_FUNCTIONAL_H_
|
||||||
|
|
Loading…
Reference in New Issue