honor IOV_MAX when using writev and readv

This commit is contained in:
Arvid Norberg 2011-09-05 05:47:50 +00:00
parent bc1e47a486
commit 43c9e640ab
3 changed files with 103 additions and 65 deletions

View File

@ -90,6 +90,7 @@
incoming connection
* added more detailed instrumentation of the disk I/O thread
* honor IOV_MAX when using writev and readv
* don't post 'operation aborted' UDP errors when changing listen port
* fix tracker retry logic, where in some configurations the next tier would not be tried
* fixed bug in http seeding logic (introduced in 0.15.7)
@ -98,7 +99,7 @@
* add reset_piece_deadline function
* fix merkle tree torrent assert
0.15.67 release
0.15.7 release
* exposed set_peer_id to python binding
* improve support for merkle tree torrent creation

View File

@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/config.hpp>
#include <boost/version.hpp>
#include <stdio.h> // for snprintf
#include <limits.h> // for IOV_MAX
#if defined TORRENT_DEBUG_BUFFERS && !defined TORRENT_DISABLE_POOL_ALLOCATOR
#error TORRENT_DEBUG_BUFFERS only works if you also disable pool allocators
@ -393,6 +394,14 @@ inline int snprintf(char* buf, int len, char const* fmt, ...)
#define TORRENT_HAS_STRDUP 1
#endif
#if !defined TORRENT_IOV_MAX
#ifdef IOV_MAX
#define TORRENT_IOV_MAX IOV_MAX
#else
#define TORRENT_IOV_MAX INT_MAX
#endif
#endif
#if !defined(TORRENT_READ_HANDLER_MAX_SIZE)
# define TORRENT_READ_HANDLER_MAX_SIZE 256
#endif

View File

@ -1182,40 +1182,54 @@ namespace libtorrent
}
#if TORRENT_USE_READV
ret = 0;
while (num_bufs > 0)
{
int nbufs = (std::min)(num_bufs, TORRENT_IOV_MAX);
int tmp_ret = 0;
#ifdef TORRENT_LINUX
bool aligned = false;
int size = 0;
// if we're not opened in no-buffer mode, we don't need alignment
if ((m_open_mode & no_buffer) == 0) aligned = true;
if (!aligned)
{
size = bufs_size(bufs, num_bufs);
if ((size & (size_alignment()-1)) == 0) aligned = true;
}
if (aligned)
#endif // TORRENT_LINUX
{
ret = ::readv(m_fd, bufs, num_bufs);
if (ret < 0)
bool aligned = false;
int size = 0;
// if we're not opened in no-buffer mode, we don't need alignment
if ((m_open_mode & no_buffer) == 0) aligned = true;
if (!aligned)
{
ec.assign(errno, get_posix_category());
return -1;
size = bufs_size(bufs, nbufs);
if ((size & (size_alignment()-1)) == 0) aligned = true;
}
return ret;
}
#ifdef TORRENT_LINUX
file::iovec_t* temp_bufs = TORRENT_ALLOCA(file::iovec_t, num_bufs);
memcpy(temp_bufs, bufs, sizeof(file::iovec_t) * num_bufs);
iovec_t& last = temp_bufs[num_bufs-1];
last.iov_len = (last.iov_len & ~(size_alignment()-1)) + m_page_size;
ret = ::readv(m_fd, temp_bufs, num_bufs);
if (ret < 0)
{
ec.assign(errno, get_posix_category());
return -1;
}
return (std::min)(ret, size_type(size));
if (aligned)
#endif // TORRENT_LINUX
{
tmp_ret = ::readv(m_fd, bufs, nbufs);
if (tmp_ret < 0)
{
ec.assign(errno, get_posix_category());
return -1;
}
ret += tmp_ret;
}
#ifdef TORRENT_LINUX
else
{
file::iovec_t* temp_bufs = TORRENT_ALLOCA(file::iovec_t, nbufs);
memcpy(temp_bufs, bufs, sizeof(file::iovec_t) * nbufs);
iovec_t& last = temp_bufs[nbufs-1];
last.iov_len = (last.iov_len & ~(size_alignment()-1)) + m_page_size;
tmp_ret = ::readv(m_fd, temp_bufs, nbufs);
if (tmp_ret < 0)
{
ec.assign(errno, get_posix_category());
return -1;
}
ret += (std::min)(tmp_ret, size_type(size));
}
#endif // TORRENT_LINUX
num_bufs -= nbufs;
bufs += nbufs;
}
return ret;
#else // TORRENT_USE_READV
@ -1412,46 +1426,60 @@ namespace libtorrent
#if TORRENT_USE_WRITEV
ret = 0;
while (num_bufs > 0)
{
int nbufs = (std::min)(num_bufs, TORRENT_IOV_MAX);
int tmp_ret = 0;
#ifdef TORRENT_LINUX
bool aligned = false;
int size = 0;
// if we're not opened in no-buffer mode, we don't need alignment
if ((m_open_mode & no_buffer) == 0) aligned = true;
if (!aligned)
{
size = bufs_size(bufs, num_bufs);
if ((size & (size_alignment()-1)) == 0) aligned = true;
}
if (aligned)
#endif
{
ret = ::writev(m_fd, bufs, num_bufs);
if (ret < 0)
bool aligned = false;
int size = 0;
// if we're not opened in no-buffer mode, we don't need alignment
if ((m_open_mode & no_buffer) == 0) aligned = true;
if (!aligned)
{
ec.assign(errno, get_posix_category());
return -1;
size = bufs_size(bufs, nbufs);
if ((size & (size_alignment()-1)) == 0) aligned = true;
}
if (aligned)
#endif
{
tmp_ret = ::writev(m_fd, bufs, nbufs);
if (tmp_ret < 0)
{
ec.assign(errno, get_posix_category());
return -1;
}
ret += tmp_ret;
}
return ret;
}
#ifdef TORRENT_LINUX
file::iovec_t* temp_bufs = TORRENT_ALLOCA(file::iovec_t, num_bufs);
memcpy(temp_bufs, bufs, sizeof(file::iovec_t) * num_bufs);
iovec_t& last = temp_bufs[num_bufs-1];
last.iov_len = (last.iov_len & ~(size_alignment()-1)) + size_alignment();
ret = ::writev(m_fd, temp_bufs, num_bufs);
if (ret < 0)
{
ec.assign(errno, get_posix_category());
return -1;
}
if (ftruncate(m_fd, file_offset + size) < 0)
{
ec.assign(errno, get_posix_category());
return -1;
}
return (std::min)(ret, size_type(size));
else
{
file::iovec_t* temp_bufs = TORRENT_ALLOCA(file::iovec_t, nbufs);
memcpy(temp_bufs, bufs, sizeof(file::iovec_t) * nbufs);
iovec_t& last = temp_bufs[nbufs-1];
last.iov_len = (last.iov_len & ~(size_alignment()-1)) + size_alignment();
tmp_ret = ::writev(m_fd, temp_bufs, nbufs);
if (tmp_ret < 0)
{
ec.assign(errno, get_posix_category());
return -1;
}
if (ftruncate(m_fd, file_offset + size) < 0)
{
ec.assign(errno, get_posix_category());
return -1;
}
ret += (std::min)(tmp_ret, size_type(size));
}
#endif // TORRENT_LINUX
num_bufs -= nbufs;
bufs += nbufs;
}
return ret;
#else // TORRENT_USE_WRITEV
ret = 0;