0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-25 15:04:10 +01:00

ircd: Preliminary AIO experimental stub on linux platforms.

This commit is contained in:
Jason Volk 2018-01-09 16:48:05 -08:00
parent 78c2af094e
commit 6a552e349e
4 changed files with 164 additions and 68 deletions

View file

@ -121,6 +121,7 @@ try
sigs.add(SIGTERM);
sigs.add(SIGUSR1);
sigs.add(SIGUSR2);
sigs.add(SIGIO);
sigs.async_wait(sigfd_handler);
// Because we registered signal handlers with the io_context, ios->run()
@ -211,6 +212,7 @@ catch(const std::exception &e)
return false;
}
static void handle_io();
static void handle_usr2();
static void handle_usr1();
static void handle_quit();
@ -240,6 +242,7 @@ sigfd_handler(const boost::system::error_code &ec,
switch(signum)
{
case SIGIO: handle_io(); break;
case SIGUSR1: handle_usr1(); break;
case SIGUSR2: handle_usr2(); break;
case SIGINT: handle_interruption(); break;
@ -288,6 +291,17 @@ catch(const std::exception &e)
ircd::log::error("SIGUSR2 handler: %s", e.what());
}
void
handle_io()
try
{
ircd::fs::notify();
}
catch(const std::exception &e)
{
ircd::log::error("SIGIO handler: %s", e.what());
}
void
handle_hangup()
try

View file

@ -438,6 +438,9 @@ RB_CHK_SYSHEADER([winsock2.h], [WINSOCK2_H])
RB_CHK_SYSHEADER([ws2tcpip.h], [WS2TCPIP_H])
RB_CHK_SYSHEADER([iphlpapi.h], [IPHLPAPI_H])
dnl linux platform
RB_CHK_SYSHEADER([aio.h], [AIO_H])
dnl experimental
RB_CHK_SYSHEADER([experimental/string_view], [EXPERIMENTAL_STRING_VIEW])
RB_CHK_SYSHEADER([experimental/optional], [EXPERIMENTAL_OPTIONAL])
@ -499,6 +502,16 @@ AM_COND_IF(INTERIX,
],[])
AM_COND_IF(LINUX,
[
AC_ARG_ENABLE(aio,
AC_HELP_STRING([--enable-aio], [Enable AIO support on Linux platforms]),
[
IRCD_DEFINE(USE_AIO, [1], [Define to 1 if you want AIO support on linux])
LIBS="$LIBS -rt"
],[])
],[])
dnl ***************************************************************************
dnl Installation Layout

View file

@ -45,6 +45,9 @@
/// during IOs.
namespace ircd::fs
{
struct aio;
struct init;
IRCD_EXCEPTION(ircd::error, error)
IRCD_EXCEPTION(error, filesystem_error)
@ -101,11 +104,13 @@ namespace ircd::fs
bool overwrite(const std::string &name, const const_raw_buffer &buf);
bool overwrite(const string_view &name, const const_raw_buffer &buf);
struct init;
void notify();
}
struct ircd::fs::init
{
std::unique_ptr<fs::aio> aio;
init();
~init() noexcept;
};

View file

@ -26,6 +26,10 @@
#include <boost/filesystem.hpp>
#include <ircd/asio.h>
#ifdef IRCD_USE_AIO
#include <RB_INC_AIO_H
#endif
namespace ircd::fs
{
using namespace boost::filesystem;
@ -54,6 +58,16 @@ ircd::fs::paths
{ "db", DBPATH },
}};
ircd::fs::init::init()
:aio{std::make_unique<fs::aio>()}
{
}
ircd::fs::init::~init()
noexcept
{
}
bool
ircd::fs::write(const std::string &path,
const const_raw_buffer &buf)
@ -89,72 +103,6 @@ ircd::fs::append(const std::string &path,
return true;
}
ircd::fs::init::init()
{
#if 0
struct aioinit aio {0};
aio.aio_threads = 0;
aio.aio_num = 64;
aio.aio_idle_time = 0;
aio_init(&aio);
#endif
}
ircd::fs::init::~init()
noexcept
{
}
#if 0 //_WIN32
namespace ircd::fs
{
}
/// Reads the file at path into a string; yields your ircd::ctx.
///
std::string
ircd::fs::read(const std::string &path)
{
const int fd
{
syscall(::open, path.c_str(), O_CLOEXEC, O_RDONLY)
};
const unwind close{[&fd]
{
syscall(::close, fd);
}};
struct stat stat;
syscall(::fstat, fd, &stat);
const auto &size{stat.st_size};
std::string ret(size, char{});
const mutable_buffer buf
{
const_cast<char *>(ret.data()), ret.size()
};
struct aiocb cb
{
fd, 0, data(buf), size(buf), 0
};
syscall(::aio_read, &cb);
struct aiocb cbs[]
{
&cb
};
syscall(::aio_suspend, &cbs, sizeof(cbs) / sizeof(aiocb), nullptr);
ret.resize(read);
return ret;
}
#else
std::string
ircd::fs::read(const std::string &path)
{
@ -164,7 +112,6 @@ ircd::fs::read(const std::string &path)
std::istream_iterator<char> e{};
return std::string{b, e};
}
#endif
ircd::string_view
ircd::fs::read(const string_view &path,
@ -336,3 +283,120 @@ catch(const std::out_of_range &e)
{
return nullptr;
}
///////////////////////////////////////////////////////////////////////////////
//
// linux aio
//
namespace ircd::fs
{
ctx::ctx *waiter;
}
void
ircd::fs::notify()
{
if(waiter)
notify(*waiter);
}
#ifndef IRCD_USE_AIO
struct ircd::fs::aio
{
aio() {}
~aio() noexcept {}
};
#else
struct ircd::fs::aio
{
aioinit init {0};
std::string read(const std::string &path);
aio();
~aio() noexcept;
};
ircd::fs::aio::aio()
{
init.aio_threads = 0;
init.aio_num = 64;
init.aio_idle_time = 0;
aio_init(&init);
auto test{[this]
{
const auto got{this->read("/etc/passwd")};
std::cout << "got: " << got << std::endl;
}};
ircd::context
{
"aiotest", context::POST | context::DETACH, test
};
}
ircd::fs::aio::~aio()
noexcept
{
}
/// Reads the file at path into a string; yields your ircd::ctx.
///
std::string
ircd::fs::aio::read(const std::string &path)
{
const auto fd
{
syscall(::open, path.c_str(), O_CLOEXEC, O_RDONLY)
};
const unwind close{[&fd]
{
syscall(::close, fd);
}};
struct stat stat;
syscall(::fstat, fd, &stat);
const auto &size{stat.st_size};
std::string ret(size, char{});
const mutable_buffer buf
{
const_cast<char *>(ret.data()), ret.size()
};
struct aiocb cb {0};
cb.aio_fildes = fd;
cb.aio_offset = 0;
cb.aio_buf = buffer::data(buf);
cb.aio_nbytes = buffer::size(buf);
cb.aio_reqprio = 0;
cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
cb.aio_sigevent.sigev_signo = SIGIO;
cb.aio_sigevent.sigev_value.sival_ptr = nullptr;
syscall(::aio_read, &cb);
waiter = ctx::current;
int errval; do
{
ctx::wait();
}
while((errval = ::aio_error(&cb)) == EINPROGRESS);
const ssize_t bytes
{
syscall(::aio_return, &cb)
};
assert(bytes >= 0);
ret.resize(size_t(bytes));
return ret;
}
#endif