From 12b949525df1aba390ec6c2bcfb406bbcf6a8df5 Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Fri, 5 Mar 2021 22:42:45 +0100 Subject: [PATCH] Add asynchronous `readv` method for filesystem_v2 --- include/dwarfs/filesystem_v2.h | 9 +++++++ include/dwarfs/inode_reader_v2.h | 9 +++++++ src/dwarfs/filesystem_v2.cpp | 17 ++++++++++--- src/dwarfs/inode_reader_v2.cpp | 42 +++++++++++++++++++++++--------- 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/include/dwarfs/filesystem_v2.h b/include/dwarfs/filesystem_v2.h index 62b013c3..18067171 100644 --- a/include/dwarfs/filesystem_v2.h +++ b/include/dwarfs/filesystem_v2.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ struct filesystem_options; struct rewrite_options; struct iovec_read_buf; +class block_range; class filesystem_writer; class logger; class mmif; @@ -146,6 +148,11 @@ class filesystem_v2 { return impl_->readv(inode, buf, size, offset); } + folly::Expected>, int> + readv(uint32_t inode, size_t size, off_t offset) const { + return impl_->readv(inode, size, offset); + } + class impl { public: virtual ~impl() = default; @@ -180,6 +187,8 @@ class filesystem_v2 { read(uint32_t inode, char* buf, size_t size, off_t offset) const = 0; virtual ssize_t readv(uint32_t inode, iovec_read_buf& buf, size_t size, off_t offset) const = 0; + virtual folly::Expected>, int> + readv(uint32_t inode, size_t size, off_t offset) const = 0; }; private: diff --git a/include/dwarfs/inode_reader_v2.h b/include/dwarfs/inode_reader_v2.h index 48d3d62f..07578731 100644 --- a/include/dwarfs/inode_reader_v2.h +++ b/include/dwarfs/inode_reader_v2.h @@ -28,6 +28,8 @@ #include +#include + #include "dwarfs/metadata_types.h" namespace dwarfs { @@ -53,6 +55,11 @@ class inode_reader_v2 { return impl_->readv(buf, size, offset, chunks); } + folly::Expected>, int> + readv(size_t size, off_t offset, chunk_range chunks) const { + return impl_->readv(size, offset, chunks); + } + void dump(std::ostream& os, const std::string& indent, chunk_range chunks) const { impl_->dump(os, indent, chunks); @@ -66,6 +73,8 @@ class inode_reader_v2 { read(char* buf, size_t size, off_t offset, chunk_range chunks) const = 0; virtual ssize_t readv(iovec_read_buf& buf, size_t size, off_t offset, chunk_range chunks) const = 0; + virtual folly::Expected>, int> + readv(size_t size, off_t offset, chunk_range chunks) const = 0; virtual void dump(std::ostream& os, const std::string& indent, chunk_range chunks) const = 0; }; diff --git a/src/dwarfs/filesystem_v2.cpp b/src/dwarfs/filesystem_v2.cpp index 688df457..fd0adac6 100644 --- a/src/dwarfs/filesystem_v2.cpp +++ b/src/dwarfs/filesystem_v2.cpp @@ -21,7 +21,6 @@ #include #include -#include #include #include @@ -209,6 +208,8 @@ class filesystem_ : public filesystem_v2::impl { read(uint32_t inode, char* buf, size_t size, off_t offset) const override; ssize_t readv(uint32_t inode, iovec_read_buf& buf, size_t size, off_t offset) const override; + folly::Expected>, int> + readv(uint32_t inode, size_t size, off_t offset) const override; private: LOG_PROXY_DECL(LoggerPolicy); @@ -382,7 +383,7 @@ ssize_t filesystem_::read(uint32_t inode, char* buf, size_t size, if (auto chunks = meta_.get_chunks(inode)) { return ir_.read(buf, size, offset, *chunks); } - return -1; + return -EBADF; } template @@ -391,7 +392,17 @@ ssize_t filesystem_::readv(uint32_t inode, iovec_read_buf& buf, if (auto chunks = meta_.get_chunks(inode)) { return ir_.readv(buf, size, offset, *chunks); } - return -1; + return -EBADF; +} + +template +folly::Expected>, int> +filesystem_::readv(uint32_t inode, size_t size, + off_t offset) const { + if (auto chunks = meta_.get_chunks(inode)) { + return ir_.readv(size, offset, *chunks); + } + return folly::makeUnexpected(-EBADF); } } // namespace diff --git a/src/dwarfs/inode_reader_v2.cpp b/src/dwarfs/inode_reader_v2.cpp index 2bdbbcdd..056f13db 100644 --- a/src/dwarfs/inode_reader_v2.cpp +++ b/src/dwarfs/inode_reader_v2.cpp @@ -64,10 +64,15 @@ class inode_reader_ : public inode_reader_v2::impl { read(char* buf, size_t size, off_t offset, chunk_range chunks) const override; ssize_t readv(iovec_read_buf& buf, size_t size, off_t offset, chunk_range chunks) const override; + folly::Expected>, int> + readv(size_t size, off_t offset, chunk_range chunks) const override; void dump(std::ostream& os, const std::string& indent, chunk_range chunks) const override; private: + folly::Expected>, int> + read(size_t size, off_t offset, chunk_range chunks) const; + template ssize_t read(size_t size, off_t offset, chunk_range chunks, const StoreFunc& store) const; @@ -89,16 +94,18 @@ void inode_reader_::dump(std::ostream& os, } template -template -ssize_t -inode_reader_::read(size_t size, off_t offset, chunk_range chunks, - const StoreFunc& store) const { +folly::Expected>, int> +inode_reader_::readv(size_t size, off_t offset, + chunk_range chunks) const { if (offset < 0) { - return -EINVAL; + return folly::makeUnexpected(-EINVAL); } + // request ranges from block cache + std::vector> ranges; + if (size == 0 || chunks.empty()) { - return 0; + return ranges; } auto it = chunks.begin(); @@ -118,19 +125,16 @@ inode_reader_::read(size_t size, off_t offset, chunk_range chunks, if (it == end) { // offset beyond EOF; TODO: check if this should rather be -EINVAL - return 0; + return ranges; } - // request ranges from block cache - std::vector> ranges; - for (size_t num_read = 0; it != end && num_read < size; ++it) { size_t chunksize = it->size() - offset; size_t chunkoff = it->offset() + offset; if (chunksize == 0) { LOG_ERROR << "invalid zero-sized chunk"; - return -EIO; + return folly::makeUnexpected(-EIO); } if (num_read + chunksize > size) { @@ -143,10 +147,24 @@ inode_reader_::read(size_t size, off_t offset, chunk_range chunks, offset = 0; } + return ranges; +} + +template +template +ssize_t +inode_reader_::read(size_t size, off_t offset, chunk_range chunks, + const StoreFunc& store) const { + auto ranges = readv(size, offset, chunks); + + if (!ranges) { + return ranges.error(); + } + try { // now fill the buffer size_t num_read = 0; - for (auto& r : ranges) { + for (auto& r : ranges.value()) { auto br = r.get(); store(num_read, br); num_read += br.size();