#ifndef BLOCK_CACHE_IO_ENGINE_H #define BLOCK_CACHE_IO_ENGINE_H #include "base/types.h" #include "base/unique_handle.h" #include #include #include #include #include #include #include #ifndef PAGE_SIZE #define PAGE_SIZE sysconf(_SC_PAGE_SIZE) #endif //---------------------------------------------------------------- namespace bcache { using base::sector_t; using base::SECTOR_SHIFT; // Virtual base class to aid unit testing class io_engine { public: enum mode { M_READ_ONLY, M_READ_WRITE }; enum dir { D_READ, D_WRITE }; enum sharing { EXCLUSIVE, SHARED }; io_engine() {} virtual ~io_engine() {} using handle = unsigned; virtual handle open_file(std::string const &path, mode m, sharing s = EXCLUSIVE) = 0; virtual void close_file(handle h) = 0; // returns false if there are insufficient resources to // queue the IO virtual bool issue_io(handle h, dir d, sector_t b, sector_t e, void *data, unsigned context) = 0; // returns (success, context) using wait_result = std::pair; virtual boost::optional wait() = 0; virtual boost::optional wait(unsigned µsec) = 0; private: io_engine(io_engine const &) = delete; io_engine &operator =(io_engine const &) = delete; }; //-------------------------------- class control_block_set { public: control_block_set(unsigned nr); iocb *alloc(unsigned context); void free(iocb *); unsigned context(iocb *) const; private: struct cblock { unsigned context; struct iocb cb; }; std::set free_cbs_; std::vector cbs_; }; //---------------- class aio_engine : public io_engine { public: // max_io is the maximum nr of concurrent ios expected aio_engine(unsigned max_io); ~aio_engine(); using handle = unsigned; virtual handle open_file(std::string const &path, mode m, sharing s = EXCLUSIVE); virtual void close_file(handle h); // Returns false if queueing the io failed virtual bool issue_io(handle h, dir d, sector_t b, sector_t e, void *data, unsigned context); virtual boost::optional wait(); virtual boost::optional wait(unsigned µsec); private: static struct timespec micro_to_ts(unsigned micro); static unsigned ts_to_micro(timespec const &ts); boost::optional wait_(timespec *ts); std::list descriptors_; io_context_t aio_context_; control_block_set cbs_; aio_engine(io_engine const &) = delete; aio_engine &operator =(io_engine const &) = delete; }; } //---------------------------------------------------------------- #endif