From b0d1b5aed5eb37b47390196a5fccf4a1a589b44f Mon Sep 17 00:00:00 2001 From: rokinsky Date: Sun, 17 Nov 2019 10:58:04 +0100 Subject: [PATCH] Added initial seastarfs file implementation --- CMakeLists.txt | 3 + include/seastar/fs/file.hh | 59 +++++++++++++++ include/seastar/util/file_utils.hh | 55 ++++++++++++++ src/fs/file.cc | 112 +++++++++++++++++++++++++++++ tests/unit/CMakeLists.txt | 3 + tests/unit/seastarfs_test.cc | 64 +++++++++++++++++ 6 files changed, 296 insertions(+) create mode 100644 include/seastar/fs/file.hh create mode 100644 include/seastar/util/file_utils.hh create mode 100644 src/fs/file.cc create mode 100644 tests/unit/seastarfs_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index e136e32b60b..96a15355c53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -457,6 +457,7 @@ add_library (seastar STATIC include/seastar/core/units.hh include/seastar/core/vector-data-sink.hh include/seastar/core/weak_ptr.hh + include/seastar/fs/file.hh include/seastar/http/api_docs.hh include/seastar/http/common.hh include/seastar/http/exception.hh @@ -515,6 +516,7 @@ add_library (seastar STATIC include/seastar/util/conversions.hh include/seastar/util/defer.hh include/seastar/util/eclipse.hh + include/seastar/util/file_utils.hh include/seastar/util/function_input_iterator.hh include/seastar/util/gcc6-concepts.hh include/seastar/util/indirect.hh @@ -562,6 +564,7 @@ add_library (seastar STATIC src/core/uname.cc src/core/vla.hh src/core/io_queue.cc + src/fs/file.cc src/http/api_docs.cc src/http/common.cc src/http/file_handler.cc diff --git a/include/seastar/fs/file.hh b/include/seastar/fs/file.hh new file mode 100644 index 00000000000..5c16ba4b66d --- /dev/null +++ b/include/seastar/fs/file.hh @@ -0,0 +1,59 @@ +/* + * This file is open source software, licensed to you under the terms + * of the Apache License, Version 2.0 (the "License"). See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. You may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * Copyright (C) 2019 ScyllaDB + */ + +#pragma once + +#include +#include +#include + +namespace seastar { + +namespace fs { + +class seastarfs_file_impl : public file_impl { + block_device _block_device; + open_flags _open_flags; +public: + seastarfs_file_impl(block_device dev, open_flags flags); + ~seastarfs_file_impl() override = default; + + future write_dma(uint64_t pos, const void* buffer, size_t len, const io_priority_class& pc) override; + future write_dma(uint64_t pos, std::vector iov, const io_priority_class& pc) override; + future read_dma(uint64_t pos, void* buffer, size_t len, const io_priority_class& pc) override; + future read_dma(uint64_t pos, std::vector iov, const io_priority_class& pc) override; + future<> flush() override; + future stat() override; + future<> truncate(uint64_t length) override; + future<> discard(uint64_t offset, uint64_t length) override; + future<> allocate(uint64_t position, uint64_t length) override; + future size() override; + future<> close() noexcept override; + std::unique_ptr dup() override; + subscription list_directory(std::function (directory_entry de)> next) override; + future> dma_read_bulk(uint64_t offset, size_t range_size, const io_priority_class& pc) override; +}; + +future open_file_dma(sstring name, open_flags flags); + +} + +} diff --git a/include/seastar/util/file_utils.hh b/include/seastar/util/file_utils.hh new file mode 100644 index 00000000000..62272e9b83b --- /dev/null +++ b/include/seastar/util/file_utils.hh @@ -0,0 +1,55 @@ +/* + * This file is open source software, licensed to you under the terms + * of the Apache License, Version 2.0 (the "License"). See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. You may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * Copyright (C) 2019 ScyllaDB + */ + +#pragma once + +#include + +namespace seastar { + +namespace util { + +class temporary_file { + sstring _path; +public: + explicit temporary_file(sstring path) : _path(std::move(path) + ".XXXXXX") { + int fd = mkstemp(_path.data()); + throw_system_error_on(fd == -1); + close(fd); + } + + ~temporary_file() { + unlink(_path.data()); + } + + temporary_file(const temporary_file &) = delete; + temporary_file &operator=(const temporary_file &) = delete; + temporary_file(temporary_file &&) noexcept = delete; + temporary_file &operator=(temporary_file &&) noexcept = delete; + + const sstring& path() const { + return _path; + } +}; + +} + +} diff --git a/src/fs/file.cc b/src/fs/file.cc new file mode 100644 index 00000000000..0c34399c906 --- /dev/null +++ b/src/fs/file.cc @@ -0,0 +1,112 @@ +/* + * This file is open source software, licensed to you under the terms + * of the Apache License, Version 2.0 (the "License"). See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. You may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * Copyright (C) 2019 ScyllaDB + */ + +#include +#include +#include + +namespace seastar { + +namespace fs { + +seastarfs_file_impl::seastarfs_file_impl(block_device dev, open_flags flags) + : _block_device(std::move(dev)) + , _open_flags(flags) {} + +future +seastarfs_file_impl::write_dma(uint64_t pos, const void *buffer, size_t len, const io_priority_class &pc) { + return _block_device.write(pos, buffer, len); +} + +future +seastarfs_file_impl::write_dma(uint64_t pos, std::vector iov, const io_priority_class &pc) { + throw std::bad_function_call(); +} + +future +seastarfs_file_impl::read_dma(uint64_t pos, void *buffer, size_t len, const io_priority_class &pc) { + return _block_device.read(pos, buffer, len); +} + +future +seastarfs_file_impl::read_dma(uint64_t pos, std::vector iov, const io_priority_class &pc) { + throw std::bad_function_call(); +} + +future<> +seastarfs_file_impl::flush() { + return _block_device.flush(); +} + +future +seastarfs_file_impl::stat() { + throw std::bad_function_call(); +} + +future<> +seastarfs_file_impl::truncate(uint64_t) { + throw std::bad_function_call(); +} + +future<> +seastarfs_file_impl::discard(uint64_t offset, uint64_t length) { + throw std::bad_function_call(); +} + +future<> +seastarfs_file_impl::allocate(uint64_t position, uint64_t length) { + throw std::bad_function_call(); +} + +future +seastarfs_file_impl::size() { + throw std::bad_function_call(); +} + +future<> +seastarfs_file_impl::close() noexcept { + return _block_device.close(); +} + +std::unique_ptr +seastarfs_file_impl::dup() { + throw std::bad_function_call(); +} + +subscription +seastarfs_file_impl::list_directory(std::function(directory_entry de)> next) { + throw std::bad_function_call(); +} + +future> +seastarfs_file_impl::dma_read_bulk(uint64_t offset, size_t range_size, const io_priority_class &pc) { + throw std::bad_function_call(); +} + +future open_file_dma(sstring name, open_flags flags) { + return open_block_device(name).then([f = std::move(flags)] (block_device bd) { + return file(make_shared(std::move(bd), f)); + }); +} + +} + +} diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index d2e9c0c488b..2aeb2a3cff2 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -345,6 +345,9 @@ seastar_add_test (rpc loopback_socket.hh rpc_test.cc) +seastar_add_test (seastarfs + SOURCES seastarfs_test.cc) + seastar_add_test (semaphore SOURCES semaphore_test.cc) diff --git a/tests/unit/seastarfs_test.cc b/tests/unit/seastarfs_test.cc new file mode 100644 index 00000000000..9aac1246321 --- /dev/null +++ b/tests/unit/seastarfs_test.cc @@ -0,0 +1,64 @@ +/* + * This file is open source software, licensed to you under the terms + * of the Apache License, Version 2.0 (the "License"). See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. You may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * Copyright (C) 2019 ScyllaDB + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace seastar; + +SEASTAR_TEST_CASE(parallel_read_write_test) { + constexpr auto max = 16 * MB; + constexpr auto path = "/tmp/seastarfs"; + + return async([] { + const auto tf = util::temporary_file(path); + auto ft = fs::open_file_dma(tf.path(), open_flags::rw).get0(); + static auto alignment = ft.memory_dma_alignment(); + + parallel_for_each(boost::irange(0, max / alignment), [&ft] (auto i) { + auto wbuf = allocate_aligned_buffer(alignment, alignment); + std::fill(wbuf.get(), wbuf.get() + alignment, i); + auto wb = wbuf.get(); + + return ft.dma_write(i * alignment, wb, alignment).then( + [&ft, i, wbuf = std::move(wbuf)](size_t ret) mutable { + BOOST_REQUIRE(ret == alignment); + auto rbuf = allocate_aligned_buffer(alignment, alignment); + auto rb = rbuf.get(); + return ft.dma_read(i * alignment, rb, alignment).then( + [ft, rbuf = std::move(rbuf), wbuf = std::move(wbuf)] (auto ret) { + BOOST_REQUIRE(ret == alignment); + BOOST_REQUIRE(std::equal(rbuf.get(), rbuf.get() + alignment, wbuf.get())); + }); + }); + }).wait(); + + ft.flush().wait(); + ft.close().wait(); + seastar_logger.info("done"); + }); +}