// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2018 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. #pragma once #define HAVE_AIO_H #include namespace ircd::fs { void prefetch__aio(const fd &, const size_t &, const read_opts &); const_buffer write__aio(const fd &, const const_buffer &, const write_opts &); const_buffer read__aio(const fd &, const mutable_buffer &, const read_opts &); void fdsync__aio(const fd &, const fsync_opts &); void fsync__aio(const fd &, const fsync_opts &); } /// AIO context instance. Right now this is a singleton with an extern /// instance at fs::aioctx. struct ircd::fs::aio { struct request; /// Maximum number of events we can submit to kernel static const size_t MAX_EVENTS; /// Internal semaphore for synchronization of this object ctx::dock dock; /// The semaphore value for the eventfd which we keep here. uint64_t semval {0}; /// An eventfd which will be notified by the kernel; we integrate this with /// the ircd io_service core epoll() event loop. The EFD_SEMAPHORE flag is /// not used to reduce the number of triggers. We can collect multiple AIO /// completions after a single trigger to this fd. Because EFD_SEMAPHORE is /// not set, the semval which is kept above will reflect a hint for how /// many AIO's are done. asio::posix::stream_descriptor resfd; /// Handler to the io context we submit requests to the kernel with aio_context_t idp {0}; // Callback stack invoked when the sigfd is notified of completed events. void handle_event(const io_event &) noexcept; void handle_events() noexcept; void handle(const boost::system::error_code &, const size_t) noexcept; void set_handle(); bool wait(); bool interrupt(); aio(); ~aio() noexcept; }; /// Generic request control block. struct ircd::fs::aio::request :iocb { struct read; struct write; struct fdsync; struct fsync; ssize_t retval {std::numeric_limits::min()}; ssize_t errcode {0}; ctx::ctx *waiter {ctx::current}; public: size_t operator()(); void cancel(); request(const int &fd); ~request() noexcept; }; /// Read request control block struct ircd::fs::aio::request::read :request { std::array iov; read(const int &fd, const mutable_buffer &, const read_opts &); }; /// Write request control block struct ircd::fs::aio::request::write :request { std::array iov; write(const int &fd, const const_buffer &, const write_opts &); }; /// fdsync request control block struct ircd::fs::aio::request::fdsync :request { fdsync(const int &fd, const fsync_opts &); }; /// fsync request control block struct ircd::fs::aio::request::fsync :request { fsync(const int &fd, const fsync_opts &); };