mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 15:33:54 +01:00
ircd::fs: Handle partial reads internally with 'all' option.
This commit is contained in:
parent
c3cf4c02dd
commit
bb3a68a95e
2 changed files with 42 additions and 4 deletions
|
@ -51,6 +51,12 @@ struct ircd::fs::read_opts
|
||||||
/// available or not enabled, or doesn't support this operation, setting
|
/// available or not enabled, or doesn't support this operation, setting
|
||||||
/// this has no effect.
|
/// this has no effect.
|
||||||
bool aio {true};
|
bool aio {true};
|
||||||
|
|
||||||
|
/// Yields the ircd::ctx until the buffers are full or EOF. This performs
|
||||||
|
/// the unix incremental read loop internally. When this option is true,
|
||||||
|
/// any return value from a function in the read suite will not be a
|
||||||
|
/// partial value requiring another invocation of read.
|
||||||
|
bool all {true};
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
inline
|
||||||
|
|
40
ircd/fs.cc
40
ircd/fs.cc
|
@ -564,6 +564,11 @@ ircd::fs::flush(const fd &fd,
|
||||||
// fs/read.h
|
// fs/read.h
|
||||||
//
|
//
|
||||||
|
|
||||||
|
namespace ircd::fs
|
||||||
|
{
|
||||||
|
static size_t read(const fd &, const const_iovec_view &, const read_opts &);
|
||||||
|
}
|
||||||
|
|
||||||
ircd::fs::read_opts
|
ircd::fs::read_opts
|
||||||
const ircd::fs::read_opts_default
|
const ircd::fs::read_opts_default
|
||||||
{};
|
{};
|
||||||
|
@ -670,15 +675,42 @@ ircd::fs::read(const string_view &path,
|
||||||
size_t
|
size_t
|
||||||
ircd::fs::read(const fd &fd,
|
ircd::fs::read(const fd &fd,
|
||||||
const mutable_buffers &bufs,
|
const mutable_buffers &bufs,
|
||||||
|
const read_opts &opts_)
|
||||||
|
{
|
||||||
|
size_t ret(0);
|
||||||
|
read_opts opts(opts_); do
|
||||||
|
{
|
||||||
|
assert(opts.offset >= opts_.offset);
|
||||||
|
const size_t off(opts.offset - opts_.offset);
|
||||||
|
assert(off <= buffers::size(bufs));
|
||||||
|
assert(ret <= buffers::size(bufs));
|
||||||
|
const auto iov(make_iov(bufs, ret));
|
||||||
|
ret += read(fd, iov, opts);
|
||||||
|
if(!opts_.all)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(off >= ret)
|
||||||
|
break;
|
||||||
|
|
||||||
|
opts.offset = opts_.offset + ret;
|
||||||
|
}
|
||||||
|
while(ret < buffers::size(bufs));
|
||||||
|
assert(opts.offset >= opts_.offset);
|
||||||
|
assert(ret <= buffers::size(bufs));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::fs::read(const fd &fd,
|
||||||
|
const const_iovec_view &iov,
|
||||||
const read_opts &opts)
|
const read_opts &opts)
|
||||||
{
|
{
|
||||||
#ifdef IRCD_USE_AIO
|
#ifdef IRCD_USE_AIO
|
||||||
if(likely(aio::context) && opts.aio)
|
if(aio::context && opts.aio)
|
||||||
return aio::read(fd, bufs, opts);
|
return aio::read(fd, iov, opts);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const auto iov(make_iov(bufs));
|
return syscall(::preadv, fd, iov.data(), iov.size(), opts.offset);
|
||||||
return size_t(syscall(::preadv, fd, iov.data(), iov.size(), opts.offset));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in a new issue