#include "reader.h" #define BLOCK_SIZE (8 * 1024) #define MAP_SIZE (32 * 1024 * 1024) namespace reader { // ============ // = Async IO = // ============ async_t::async_t (std::string const& path) { if((fd = open(path.c_str(), O_RDONLY|O_CLOEXEC)) != -1) { fcntl(fd, F_NOCACHE, 1); struct stat buf; fstat(fd, &buf); offset = 0; file_size = buf.st_size; setup_request(); } } async_t::~async_t () { if(fd != -1) close(fd); } void async_t::setup_request () { request = NULL; if(off_t len = std::min(BLOCK_SIZE, file_size - offset)) { request = new aiocb; bzero(request, sizeof(*request)); request->aio_fildes = fd; request->aio_offset = offset; request->aio_buf = new char[len]; request->aio_nbytes = len; aio_read(request); } } io::bytes_ptr async_t::next () { if(fd == -1 || !request) return io::bytes_ptr(); int rc = aio_suspend(&request, 1, NULL); if(rc == -1) return io::bytes_ptr(); ssize_t len = aio_return(request); if(len == -1) return io::bytes_ptr(); offset += request->aio_nbytes; auto res = std::make_shared((char const*)request->aio_buf, request->aio_nbytes); delete request; setup_request(); return res; } // ================= // = Memory Mapped = // ================= mapped_t::mapped_t (std::string const& path) { offset = 0; mapped_size = 0; if((fd = open(path.c_str(), O_RDONLY|O_CLOEXEC)) != -1) { fcntl(fd, F_NOCACHE, 1); struct stat buf; fstat(fd, &buf); file_size = buf.st_size; } } mapped_t::~mapped_t () { if(mapped_size) { if(munmap(memory, mapped_size) != 0) perror("munmap"); } if(fd != -1) close(fd); } io::bytes_ptr mapped_t::next () { if(fd == -1) return io::bytes_ptr(); if(mapped_size) { if(munmap(memory, mapped_size) != 0) perror("munmap"); } offset += mapped_size; mapped_size = std::min(MAP_SIZE, file_size - offset); if(mapped_size == 0) return io::bytes_ptr(); memory = (char*)mmap(NULL, mapped_size, PROT_READ, MAP_PRIVATE, fd, offset); return std::make_shared(memory, mapped_size, false); } // =========== // = fopen() = // =========== fopen_t::fopen_t (std::string const& path) { if(fp = fopen(path.c_str(), "r")) fcntl(fileno(fp), F_NOCACHE, 1); } fopen_t::~fopen_t () { if(fp) fclose(fp); } io::bytes_ptr fopen_t::next () { if(!fp) return io::bytes_ptr(); char* buf = new char[BLOCK_SIZE]; if(size_t len = fread(buf, 1, BLOCK_SIZE, fp)) return std::make_shared(buf, len); delete[] buf; return io::bytes_ptr(); } // ========== // = open() = // ========== open_t::open_t (std::string const& path) { if((fd = open(path.c_str(), O_RDONLY|O_CLOEXEC)) != -1) fcntl(fd, F_NOCACHE, 1); } open_t::~open_t () { if(fd != -1) close(fd); } io::bytes_ptr open_t::next () { if(fd == -1) return io::bytes_ptr(); char* buf = new char[BLOCK_SIZE]; ssize_t len = read(fd, buf, BLOCK_SIZE); if(len > 0) return std::make_shared(buf, len); delete[] buf; return io::bytes_ptr(); } } /* reader */