From 5d05ef0e756a7c52673fcf78b4ab8c9ccee2154d Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 3 Mar 2010 14:29:40 +0000 Subject: [PATCH] 2010-03-03 Tatsuhiro Tsujikawa Rewritten SocketBuffer. Old implementation uses single std::string to store data and erase sent data, which is costly. New implementation uses deque to hold each data to avoid to mutate string. * src/SocketBuffer.cc * src/SocketBuffer.h --- ChangeLog | 9 +++++++++ src/SocketBuffer.cc | 36 +++++++++++++++++++++++------------- src/SocketBuffer.h | 20 +++++++++++++++++--- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index bca00aee..90fcd3d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-03-03 Tatsuhiro Tsujikawa + + Rewritten SocketBuffer. Old implementation uses single std::string + to store data and erase sent data, which is costly. New + implementation uses deque to hold each data to avoid to mutate + string. + * src/SocketBuffer.cc + * src/SocketBuffer.h + 2010-03-03 Tatsuhiro Tsujikawa Removed unused FileEntry::extracted diff --git a/src/SocketBuffer.cc b/src/SocketBuffer.cc index 447b1f69..b9fd4603 100644 --- a/src/SocketBuffer.cc +++ b/src/SocketBuffer.cc @@ -2,7 +2,7 @@ /* * aria2 - The high speed download utility * - * Copyright (C) 2006 Tatsuhiro Tsujikawa + * 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 @@ -44,13 +44,13 @@ namespace aria2 { SocketBuffer::SocketBuffer(const SharedHandle& socket): - _socket(socket) {} + _socket(socket), _offset(0) {} SocketBuffer::~SocketBuffer() {} void SocketBuffer::feedSendBuffer(const std::string& data) { - _sendbuf += data; + _bufq.push_back(data); } ssize_t SocketBuffer::feedAndSend(const std::string& data) @@ -61,21 +61,31 @@ ssize_t SocketBuffer::feedAndSend(const std::string& data) ssize_t SocketBuffer::send() { - if(_sendbuf.empty()) { - return 0; + size_t totalslen = 0; + while(!_bufq.empty()) { + const std::string& data = _bufq[0]; + const size_t size = data.size(); + ssize_t r = size-_offset; + ssize_t slen = _socket->writeData(data.data()+_offset, r); + if(slen == 0 && !_socket->wantRead() && !_socket->wantWrite()) { + throw DL_ABORT_EX(StringFormat(EX_SOCKET_SEND, + "Connection closed.").str()); + } + totalslen += slen; + if(slen < r) { + _offset += slen; + break; + } else { + _offset = 0; + _bufq.pop_front(); + } } - ssize_t len = _socket->writeData(_sendbuf.c_str(), - _sendbuf.size()); - if(len == 0 && !_socket->wantRead() && !_socket->wantWrite()) { - throw DL_ABORT_EX(StringFormat(EX_SOCKET_SEND, "Connection closed.").str()); - } - _sendbuf.erase(0, len); - return len; + return totalslen; } bool SocketBuffer::sendBufferIsEmpty() const { - return _sendbuf.empty(); + return _bufq.empty(); } } // namespace aria2 diff --git a/src/SocketBuffer.h b/src/SocketBuffer.h index 28fd29ab..eb12126a 100644 --- a/src/SocketBuffer.h +++ b/src/SocketBuffer.h @@ -2,7 +2,7 @@ /* * aria2 - The high speed download utility * - * Copyright (C) 2006 Tatsuhiro Tsujikawa + * 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 @@ -36,8 +36,11 @@ #define _D_SOCKET_BUFFER_H_ #include "common.h" -#include "SharedHandle.h" + #include +#include + +#include "SharedHandle.h" namespace aria2 { @@ -47,18 +50,29 @@ class SocketBuffer { private: SharedHandle _socket; - std::string _sendbuf; + std::deque _bufq; + + // Offset of data in _bufq[0]. SocketBuffer tries to send _bufq[0], + // but it cannot always send whole data. In this case, offset points + // to the data to be sent in the next send() call. + size_t _offset; public: SocketBuffer(const SharedHandle& socket); ~SocketBuffer(); + // Feeds data into queue. This function doesn't send data. void feedSendBuffer(const std::string& data); + // Feeds data into queue and sends data in queue. This function is + // equivalent to call feedSendBuffer() and send() sequentially. + // Returns the number of bytes sent. ssize_t feedAndSend(const std::string& data); + // Sends data in queue. Returns the number of bytes sent. ssize_t send(); + // Returns true if queue is empty. bool sendBufferIsEmpty() const; };