Use std::unique_ptr for HttpResponse instead of std::shared_ptr

pull/103/head
Tatsuhiro Tsujikawa 2013-07-03 23:42:55 +09:00
parent 7e6db8d801
commit 9a38c102dc
8 changed files with 53 additions and 66 deletions

View File

@ -129,7 +129,7 @@ void HttpConnection::sendProxyRequest
sendRequest(httpRequest, httpRequest->createProxyRequest()); sendRequest(httpRequest, httpRequest->createProxyRequest());
} }
std::shared_ptr<HttpResponse> HttpConnection::receiveResponse() std::unique_ptr<HttpResponse> HttpConnection::receiveResponse()
{ {
if(outstandingHttpRequests_.empty()) { if(outstandingHttpRequests_.empty()) {
throw DL_ABORT_EX(EX_NO_HTTP_REQUEST_ENTRY_FOUND); throw DL_ABORT_EX(EX_NO_HTTP_REQUEST_ENTRY_FOUND);
@ -140,24 +140,24 @@ std::shared_ptr<HttpResponse> HttpConnection::receiveResponse()
throw DL_RETRY_EX(EX_GOT_EOF); throw DL_RETRY_EX(EX_GOT_EOF);
} }
} }
std::shared_ptr<HttpResponse> httpResponse;
const auto& proc = outstandingHttpRequests_.front()->getHttpHeaderProcessor(); const auto& proc = outstandingHttpRequests_.front()->getHttpHeaderProcessor();
if(proc->parse(socketRecvBuffer_->getBuffer(), if(proc->parse(socketRecvBuffer_->getBuffer(),
socketRecvBuffer_->getBufferLength())) { socketRecvBuffer_->getBufferLength())) {
A2_LOG_INFO(fmt(MSG_RECEIVE_RESPONSE, A2_LOG_INFO(fmt(MSG_RECEIVE_RESPONSE,
cuid_, cuid_,
proc->getHeaderString().c_str())); proc->getHeaderString().c_str()));
httpResponse.reset(new HttpResponse()); auto httpResponse = make_unique<HttpResponse>();
httpResponse->setCuid(cuid_); httpResponse->setCuid(cuid_);
httpResponse->setHttpHeader(proc->getResult()); httpResponse->setHttpHeader(proc->getResult());
httpResponse->setHttpRequest(outstandingHttpRequests_.front()-> httpResponse->setHttpRequest(outstandingHttpRequests_.front()->
getHttpRequest()); getHttpRequest());
socketRecvBuffer_->shiftBuffer(proc->getLastBytesProcessed()); socketRecvBuffer_->shiftBuffer(proc->getLastBytesProcessed());
outstandingHttpRequests_.pop_front(); outstandingHttpRequests_.pop_front();
return httpResponse;
} else { } else {
socketRecvBuffer_->shiftBuffer(proc->getLastBytesProcessed()); socketRecvBuffer_->shiftBuffer(proc->getLastBytesProcessed());
return std::unique_ptr<HttpResponse>{};
} }
return httpResponse;
} }
bool HttpConnection::isIssued(const std::shared_ptr<Segment>& segment) const bool HttpConnection::isIssued(const std::shared_ptr<Segment>& segment) const

View File

@ -117,7 +117,7 @@ public:
* *
* @return HttpResponse or 0 if whole response header is not received * @return HttpResponse or 0 if whole response header is not received
*/ */
std::shared_ptr<HttpResponse> receiveResponse(); std::unique_ptr<HttpResponse> receiveResponse();
std::shared_ptr<HttpRequest> getFirstHttpRequest() const; std::shared_ptr<HttpRequest> getFirstHttpRequest() const;

View File

@ -60,13 +60,13 @@ HttpDownloadCommand::HttpDownloadCommand
const std::shared_ptr<Request>& req, const std::shared_ptr<Request>& req,
const std::shared_ptr<FileEntry>& fileEntry, const std::shared_ptr<FileEntry>& fileEntry,
RequestGroup* requestGroup, RequestGroup* requestGroup,
const std::shared_ptr<HttpResponse>& httpResponse, std::unique_ptr<HttpResponse> httpResponse,
const std::shared_ptr<HttpConnection>& httpConnection, const std::shared_ptr<HttpConnection>& httpConnection,
DownloadEngine* e, DownloadEngine* e,
const std::shared_ptr<SocketCore>& socket) const std::shared_ptr<SocketCore>& socket)
: DownloadCommand(cuid, req, fileEntry, requestGroup, e, socket, : DownloadCommand(cuid, req, fileEntry, requestGroup, e, socket,
httpConnection->getSocketRecvBuffer()), httpConnection->getSocketRecvBuffer()),
httpResponse_(httpResponse), httpResponse_(std::move(httpResponse)),
httpConnection_(httpConnection) httpConnection_(httpConnection)
{} {}

View File

@ -44,7 +44,7 @@ class HttpConnection;
class HttpDownloadCommand : public DownloadCommand { class HttpDownloadCommand : public DownloadCommand {
private: private:
std::shared_ptr<HttpResponse> httpResponse_; std::unique_ptr<HttpResponse> httpResponse_;
std::shared_ptr<HttpConnection> httpConnection_; std::shared_ptr<HttpConnection> httpConnection_;
protected: protected:
virtual bool prepareForNextSegment(); virtual bool prepareForNextSegment();
@ -54,7 +54,7 @@ public:
const std::shared_ptr<Request>& req, const std::shared_ptr<Request>& req,
const std::shared_ptr<FileEntry>& fileEntry, const std::shared_ptr<FileEntry>& fileEntry,
RequestGroup* requestGroup, RequestGroup* requestGroup,
const std::shared_ptr<HttpResponse>& httpResponse, std::unique_ptr<HttpResponse> httpResponse,
const std::shared_ptr<HttpConnection>& httpConnection, const std::shared_ptr<HttpConnection>& httpConnection,
DownloadEngine* e, DownloadEngine* e,
const std::shared_ptr<SocketCore>& s); const std::shared_ptr<SocketCore>& s);

View File

@ -85,7 +85,7 @@ namespace aria2 {
namespace { namespace {
std::shared_ptr<StreamFilter> getTransferEncodingStreamFilter std::shared_ptr<StreamFilter> getTransferEncodingStreamFilter
(const std::shared_ptr<HttpResponse>& httpResponse, (HttpResponse* httpResponse,
const std::shared_ptr<StreamFilter>& delegate = std::shared_ptr<StreamFilter>()) const std::shared_ptr<StreamFilter>& delegate = std::shared_ptr<StreamFilter>())
{ {
std::shared_ptr<StreamFilter> filter; std::shared_ptr<StreamFilter> filter;
@ -108,7 +108,7 @@ std::shared_ptr<StreamFilter> getTransferEncodingStreamFilter
namespace { namespace {
std::shared_ptr<StreamFilter> getContentEncodingStreamFilter std::shared_ptr<StreamFilter> getContentEncodingStreamFilter
(const std::shared_ptr<HttpResponse>& httpResponse, (HttpResponse* httpResponse,
const std::shared_ptr<StreamFilter>& delegate = std::shared_ptr<StreamFilter>()) const std::shared_ptr<StreamFilter>& delegate = std::shared_ptr<StreamFilter>())
{ {
std::shared_ptr<StreamFilter> filter; std::shared_ptr<StreamFilter> filter;
@ -152,7 +152,7 @@ HttpResponseCommand::~HttpResponseCommand() {}
bool HttpResponseCommand::executeInternal() bool HttpResponseCommand::executeInternal()
{ {
std::shared_ptr<HttpRequest> httpRequest =httpConnection_->getFirstHttpRequest(); std::shared_ptr<HttpRequest> httpRequest =httpConnection_->getFirstHttpRequest();
std::shared_ptr<HttpResponse> httpResponse = httpConnection_->receiveResponse(); auto httpResponse = httpConnection_->receiveResponse();
if(!httpResponse) { if(!httpResponse) {
// The server has not responded to our request yet. // The server has not responded to our request yet.
// For socket->wantRead() == true, setReadCheckSocket(socket) is already // For socket->wantRead() == true, setReadCheckSocket(socket) is already
@ -234,7 +234,7 @@ bool HttpResponseCommand::executeInternal()
if(statusCode == 404) { if(statusCode == 404) {
getRequestGroup()->increaseAndValidateFileNotFoundCount(); getRequestGroup()->increaseAndValidateFileNotFoundCount();
} }
return skipResponseBody(httpResponse); return skipResponseBody(std::move(httpResponse));
} }
if(getFileEntry()->isUniqueProtocol()) { if(getFileEntry()->isUniqueProtocol()) {
// Redirection should be considered here. We need to parse // Redirection should be considered here. We need to parse
@ -269,7 +269,7 @@ bool HttpResponseCommand::executeInternal()
// If both transfer-encoding and total length is specified, we // If both transfer-encoding and total length is specified, we
// assume we can do segmented downloading // assume we can do segmented downloading
if(totalLength == 0 || shouldInflateContentEncoding(httpResponse)) { if(totalLength == 0 || shouldInflateContentEncoding(httpResponse.get())) {
// we ignore content-length when inflate is required // we ignore content-length when inflate is required
getFileEntry()->setLength(0); getFileEntry()->setLength(0);
if(getRequest()->getMethod() == Request::METHOD_GET && if(getRequest()->getMethod() == Request::METHOD_GET &&
@ -279,9 +279,9 @@ bool HttpResponseCommand::executeInternal()
// server says the size of file is 0 explicitly. // server says the size of file is 0 explicitly.
getDownloadContext()->markTotalLengthIsUnknown(); getDownloadContext()->markTotalLengthIsUnknown();
} }
return handleOtherEncoding(httpResponse); return handleOtherEncoding(std::move(httpResponse));
} else { } else {
return handleDefaultEncoding(httpResponse); return handleDefaultEncoding(std::move(httpResponse));
} }
} else { } else {
#ifdef ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST
@ -308,17 +308,15 @@ bool HttpResponseCommand::executeInternal()
// Also we can't resume in this case too. So truncate the file // Also we can't resume in this case too. So truncate the file
// anyway. // anyway.
getPieceStorage()->getDiskAdaptor()->truncate(0); getPieceStorage()->getDiskAdaptor()->truncate(0);
auto teFilter = getTransferEncodingStreamFilter
(httpResponse.get(),
getContentEncodingStreamFilter(httpResponse.get()));
getDownloadEngine()->addCommand getDownloadEngine()->addCommand
(createHttpDownloadCommand (createHttpDownloadCommand(std::move(httpResponse), teFilter));
(httpResponse,
getTransferEncodingStreamFilter
(httpResponse,
getContentEncodingStreamFilter(httpResponse))));
} else { } else {
auto teFilter = getTransferEncodingStreamFilter(httpResponse.get());
getDownloadEngine()->addCommand getDownloadEngine()->addCommand
(createHttpDownloadCommand (createHttpDownloadCommand(std::move(httpResponse), teFilter));
(httpResponse,
getTransferEncodingStreamFilter(httpResponse)));
} }
return true; return true;
} }
@ -332,7 +330,7 @@ void HttpResponseCommand::updateLastModifiedTime(const Time& lastModified)
} }
bool HttpResponseCommand::shouldInflateContentEncoding bool HttpResponseCommand::shouldInflateContentEncoding
(const std::shared_ptr<HttpResponse>& httpResponse) (HttpResponse* httpResponse)
{ {
// Basically, on the fly inflation cannot be made with segment // Basically, on the fly inflation cannot be made with segment
// download, because in each segment we don't know where the date // download, because in each segment we don't know where the date
@ -347,12 +345,10 @@ bool HttpResponseCommand::shouldInflateContentEncoding
} }
bool HttpResponseCommand::handleDefaultEncoding bool HttpResponseCommand::handleDefaultEncoding
(const std::shared_ptr<HttpResponse>& httpResponse) (std::unique_ptr<HttpResponse> httpResponse)
{ {
std::shared_ptr<HttpRequest> httpRequest = httpResponse->getHttpRequest(); auto progressInfoFile = std::make_shared<DefaultBtProgressInfoFile>
std::shared_ptr<BtProgressInfoFile> progressInfoFile (getDownloadContext(), std::shared_ptr<PieceStorage>{}, getOption().get());
(new DefaultBtProgressInfoFile
(getDownloadContext(), std::shared_ptr<PieceStorage>(), getOption().get()));
getRequestGroup()->adjustFilename(progressInfoFile); getRequestGroup()->adjustFilename(progressInfoFile);
getRequestGroup()->initPieceStorage(); getRequestGroup()->initPieceStorage();
@ -361,8 +357,7 @@ bool HttpResponseCommand::handleDefaultEncoding
return true; return true;
} }
std::shared_ptr<CheckIntegrityEntry> checkEntry = auto checkEntry = getRequestGroup()->createCheckIntegrityEntry();
getRequestGroup()->createCheckIntegrityEntry();
if(!checkEntry) { if(!checkEntry) {
return true; return true;
} }
@ -370,8 +365,7 @@ bool HttpResponseCommand::handleDefaultEncoding
// We have to make sure that command that has Request object must // We have to make sure that command that has Request object must
// have segment after PieceStorage is initialized. See // have segment after PieceStorage is initialized. See
// AbstractCommand::execute() // AbstractCommand::execute()
std::shared_ptr<Segment> segment = auto segment = getSegmentMan()->getSegmentWithIndex(getCuid(), 0);
getSegmentMan()->getSegmentWithIndex(getCuid(), 0);
// pipelining requires implicit range specified. But the request for // pipelining requires implicit range specified. But the request for
// this response most likely dones't contains range header. This means // this response most likely dones't contains range header. This means
// we can't continue to use this socket because server sends all entity // we can't continue to use this socket because server sends all entity
@ -380,10 +374,9 @@ bool HttpResponseCommand::handleDefaultEncoding
if(getRequest()->getMethod() == Request::METHOD_GET && if(getRequest()->getMethod() == Request::METHOD_GET &&
segment && segment->getPositionToWrite() == 0 && segment && segment->getPositionToWrite() == 0 &&
!getRequest()->isPipeliningEnabled()) { !getRequest()->isPipeliningEnabled()) {
auto teFilter = getTransferEncodingStreamFilter(httpResponse.get());
checkEntry->pushNextCommand checkEntry->pushNextCommand
(createHttpDownloadCommand (createHttpDownloadCommand(std::move(httpResponse), teFilter));
(httpResponse,
getTransferEncodingStreamFilter(httpResponse)));
} else { } else {
getSegmentMan()->cancelSegment(getCuid()); getSegmentMan()->cancelSegment(getCuid());
getFileEntry()->poolRequest(getRequest()); getFileEntry()->poolRequest(getRequest());
@ -399,10 +392,8 @@ bool HttpResponseCommand::handleDefaultEncoding
} }
bool HttpResponseCommand::handleOtherEncoding bool HttpResponseCommand::handleOtherEncoding
(const std::shared_ptr<HttpResponse>& httpResponse) { (std::unique_ptr<HttpResponse> httpResponse) {
// We assume that RequestGroup::getTotalLength() == 0 here // We assume that RequestGroup::getTotalLength() == 0 here
std::shared_ptr<HttpRequest> httpRequest = httpResponse->getHttpRequest();
if(getOption()->getAsBool(PREF_DRY_RUN)) { if(getOption()->getAsBool(PREF_DRY_RUN)) {
getRequestGroup()->initPieceStorage(); getRequestGroup()->initPieceStorage();
onDryRunFileFound(); onDryRunFileFound();
@ -418,10 +409,8 @@ bool HttpResponseCommand::handleOtherEncoding
// In this context, knowsTotalLength() is true only when the file is // In this context, knowsTotalLength() is true only when the file is
// really zero-length. // really zero-length.
std::shared_ptr<StreamFilter> streamFilter = auto streamFilter = getTransferEncodingStreamFilter
getTransferEncodingStreamFilter (httpResponse.get(), getContentEncodingStreamFilter(httpResponse.get()));
(httpResponse,
getContentEncodingStreamFilter(httpResponse));
// If chunked transfer-encoding is specified, we have to read end of // If chunked transfer-encoding is specified, we have to read end of
// chunk markers(0\r\n\r\n, for example). // chunk markers(0\r\n\r\n, for example).
bool chunkedUsed = streamFilter && bool chunkedUsed = streamFilter &&
@ -471,8 +460,8 @@ bool HttpResponseCommand::handleOtherEncoding
#ifdef ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST
if(getDownloadContext()->isChecksumVerificationNeeded()) { if(getDownloadContext()->isChecksumVerificationNeeded()) {
A2_LOG_DEBUG("Verify checksum for zero-length file"); A2_LOG_DEBUG("Verify checksum for zero-length file");
std::shared_ptr<ChecksumCheckIntegrityEntry> entry auto entry = std::make_shared<ChecksumCheckIntegrityEntry>
(new ChecksumCheckIntegrityEntry(getRequestGroup())); (getRequestGroup());
entry->initValidator(); entry->initValidator();
getDownloadEngine()->getCheckIntegrityMan()->pushEntry(entry); getDownloadEngine()->getCheckIntegrityMan()->pushEntry(entry);
} else } else
@ -489,29 +478,28 @@ bool HttpResponseCommand::handleOtherEncoding
getSegmentMan()->getSegmentWithIndex(getCuid(), 0); getSegmentMan()->getSegmentWithIndex(getCuid(), 0);
getDownloadEngine()->addCommand getDownloadEngine()->addCommand
(createHttpDownloadCommand(httpResponse, streamFilter)); (createHttpDownloadCommand(std::move(httpResponse), streamFilter));
return true; return true;
} }
bool HttpResponseCommand::skipResponseBody bool HttpResponseCommand::skipResponseBody
(const std::shared_ptr<HttpResponse>& httpResponse) (std::unique_ptr<HttpResponse> httpResponse)
{ {
std::shared_ptr<StreamFilter> filter = auto filter = getTransferEncodingStreamFilter(httpResponse.get());
getTransferEncodingStreamFilter(httpResponse);
// We don't use Content-Encoding here because this response body is just // We don't use Content-Encoding here because this response body is just
// thrown away. // thrown away.
auto httpResponsePtr = httpResponse.get();
auto command = make_unique<HttpSkipResponseCommand> auto command = make_unique<HttpSkipResponseCommand>
(getCuid(), getRequest(), getFileEntry(), getRequestGroup(), (getCuid(), getRequest(), getFileEntry(), getRequestGroup(),
httpConnection_, httpResponse, httpConnection_, std::move(httpResponse),
getDownloadEngine(), getSocket()); getDownloadEngine(), getSocket());
command->installStreamFilter(filter); command->installStreamFilter(filter);
// If request method is HEAD or the response body is zero-length, // If request method is HEAD or the response body is zero-length,
// set command's status to real time so that avoid read check blocking // set command's status to real time so that avoid read check blocking
if(getRequest()->getMethod() == Request::METHOD_HEAD || if(getRequest()->getMethod() == Request::METHOD_HEAD ||
(httpResponse->getEntityLength() == 0 && (httpResponsePtr->getEntityLength() == 0 &&
!httpResponse->isTransferEncodingSpecified())) { !httpResponsePtr->isTransferEncodingSpecified())) {
command->setStatusRealtime(); command->setStatusRealtime();
// If entity length == 0, then socket read/write check must be disabled. // If entity length == 0, then socket read/write check must be disabled.
command->disableSocketCheck(); command->disableSocketCheck();
@ -542,14 +530,14 @@ bool decideFileAllocation
std::unique_ptr<HttpDownloadCommand> std::unique_ptr<HttpDownloadCommand>
HttpResponseCommand::createHttpDownloadCommand HttpResponseCommand::createHttpDownloadCommand
(const std::shared_ptr<HttpResponse>& httpResponse, (std::unique_ptr<HttpResponse> httpResponse,
const std::shared_ptr<StreamFilter>& filter) const std::shared_ptr<StreamFilter>& filter)
{ {
auto command = make_unique<HttpDownloadCommand> auto command = make_unique<HttpDownloadCommand>
(getCuid(), getRequest(), getFileEntry(), (getCuid(), getRequest(), getFileEntry(),
getRequestGroup(), getRequestGroup(),
httpResponse, httpConnection_, std::move(httpResponse), httpConnection_,
getDownloadEngine(), getSocket()); getDownloadEngine(), getSocket());
command->setStartupIdleTime(getOption()->getAsInt(PREF_STARTUP_IDLE_TIME)); command->setStartupIdleTime(getOption()->getAsInt(PREF_STARTUP_IDLE_TIME));
command->setLowestDownloadSpeedLimit command->setLowestDownloadSpeedLimit

View File

@ -63,13 +63,13 @@ class HttpResponseCommand : public AbstractCommand {
private: private:
std::shared_ptr<HttpConnection> httpConnection_; std::shared_ptr<HttpConnection> httpConnection_;
bool handleDefaultEncoding(const std::shared_ptr<HttpResponse>& httpResponse); bool handleDefaultEncoding(std::unique_ptr<HttpResponse> httpResponse);
bool handleOtherEncoding(const std::shared_ptr<HttpResponse>& httpResponse); bool handleOtherEncoding(std::unique_ptr<HttpResponse> httpResponse);
bool skipResponseBody(const std::shared_ptr<HttpResponse>& httpResponse); bool skipResponseBody(std::unique_ptr<HttpResponse> httpResponse);
std::unique_ptr<HttpDownloadCommand> std::unique_ptr<HttpDownloadCommand>
createHttpDownloadCommand createHttpDownloadCommand
(const std::shared_ptr<HttpResponse>& httpResponse, (std::unique_ptr<HttpResponse> httpResponse,
const std::shared_ptr<StreamFilter>& streamFilter); const std::shared_ptr<StreamFilter>& streamFilter);
void updateLastModifiedTime(const Time& lastModified); void updateLastModifiedTime(const Time& lastModified);
@ -88,8 +88,7 @@ private:
protected: protected:
bool executeInternal(); bool executeInternal();
bool shouldInflateContentEncoding bool shouldInflateContentEncoding(HttpResponse* httpResponse);
(const std::shared_ptr<HttpResponse>& httpResponse);
public: public:
HttpResponseCommand(cuid_t cuid, HttpResponseCommand(cuid_t cuid,

View File

@ -69,13 +69,13 @@ HttpSkipResponseCommand::HttpSkipResponseCommand
const std::shared_ptr<FileEntry>& fileEntry, const std::shared_ptr<FileEntry>& fileEntry,
RequestGroup* requestGroup, RequestGroup* requestGroup,
const std::shared_ptr<HttpConnection>& httpConnection, const std::shared_ptr<HttpConnection>& httpConnection,
const std::shared_ptr<HttpResponse>& httpResponse, std::unique_ptr<HttpResponse> httpResponse,
DownloadEngine* e, DownloadEngine* e,
const std::shared_ptr<SocketCore>& s) const std::shared_ptr<SocketCore>& s)
: AbstractCommand(cuid, req, fileEntry, requestGroup, e, s, : AbstractCommand(cuid, req, fileEntry, requestGroup, e, s,
httpConnection->getSocketRecvBuffer()), httpConnection->getSocketRecvBuffer()),
httpConnection_(httpConnection), httpConnection_(httpConnection),
httpResponse_(httpResponse), httpResponse_(std::move(httpResponse)),
streamFilter_(new NullSinkStreamFilter()), streamFilter_(new NullSinkStreamFilter()),
sinkFilterOnly_(true), sinkFilterOnly_(true),
totalLength_(httpResponse_->getEntityLength()), totalLength_(httpResponse_->getEntityLength()),

View File

@ -47,7 +47,7 @@ class HttpSkipResponseCommand : public AbstractCommand {
private: private:
std::shared_ptr<HttpConnection> httpConnection_; std::shared_ptr<HttpConnection> httpConnection_;
std::shared_ptr<HttpResponse> httpResponse_; std::unique_ptr<HttpResponse> httpResponse_;
std::shared_ptr<StreamFilter> streamFilter_; std::shared_ptr<StreamFilter> streamFilter_;
@ -69,7 +69,7 @@ public:
const std::shared_ptr<FileEntry>& fileEntry, const std::shared_ptr<FileEntry>& fileEntry,
RequestGroup* requestGroup, RequestGroup* requestGroup,
const std::shared_ptr<HttpConnection>& httpConnection, const std::shared_ptr<HttpConnection>& httpConnection,
const std::shared_ptr<HttpResponse>& httpResponse, std::unique_ptr<HttpResponse> httpResponse,
DownloadEngine* e, DownloadEngine* e,
const std::shared_ptr<SocketCore>& s); const std::shared_ptr<SocketCore>& s);