diff --git a/charybdis/charybdis.cc b/charybdis/charybdis.cc index fbb5e8db5..9aefe0a97 100644 --- a/charybdis/charybdis.cc +++ b/charybdis/charybdis.cc @@ -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 diff --git a/configure.ac b/configure.ac index 4b7769a63..6f8cbbd36 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/include/ircd/fs.h b/include/ircd/fs.h index 8f8da5ff5..3c53724b8 100644 --- a/include/ircd/fs.h +++ b/include/ircd/fs.h @@ -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 aio; + init(); ~init() noexcept; }; diff --git a/ircd/fs.cc b/ircd/fs.cc index e6f3ff024..138d45480 100644 --- a/ircd/fs.cc +++ b/ircd/fs.cc @@ -26,6 +26,10 @@ #include #include +#ifdef IRCD_USE_AIO + #include ()} +{ +} + +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(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 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(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