diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2022-05-07 01:35:41 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2022-05-07 01:35:41 +0100 |
commit | 5271b74ac7b6ebdbe3d1f5241e1435a94918d14d (patch) | |
tree | c8009814287eb710b2ee7c77161fb1994960cf2e | |
parent | Simplified and fixed up combined settings in fuseapp (diff) | |
download | netfs-5271b74ac7b6ebdbe3d1f5241e1435a94918d14d.tar.bz2 netfs-5271b74ac7b6ebdbe3d1f5241e1435a94918d14d.tar.xz netfs-5271b74ac7b6ebdbe3d1f5241e1435a94918d14d.zip |
Add functions for calculating the block sizes for large read/writes
-rw-r--r-- | netfs/fuse/fuseFiles.cpp | 25 | ||||
-rw-r--r-- | netfs/fuse/fuseFiles.h | 14 | ||||
-rw-r--r-- | netfs/unittests/testEdgeCases.cpp | 68 |
3 files changed, 107 insertions, 0 deletions
diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp index 3ecb37f..a44f56e 100644 --- a/netfs/fuse/fuseFiles.cpp +++ b/netfs/fuse/fuseFiles.cpp @@ -210,6 +210,31 @@ namespace NetFS { } } + FuseApp::OpenFile::BlockSizes + FuseApp::OpenFile::blockSizes(size_t total, size_t max) noexcept + { + if (max >= total) { // Simple case, all in remainder block + return {total, 0, 0}; + } + else if (total % max == 0) { // Simplish case, multiples of max + return {0, max, total / max}; + } + else { + const auto blocks = (total / max); + const auto blockSize = (total / (blocks + 1)) + 1; + const auto batchTotal = blockSize * blocks; + const auto remainder = total - batchTotal; + + return {remainder, blockSize, blocks}; + } + } + + size_t + FuseApp::OpenFile::BlockSizes::total() const noexcept + { + return size1 + (sizeN * N); + } + ssize_t FuseApp::copy_file_range(const char *, struct fuse_file_info * fi_in, off_t offset_in, const char *, struct fuse_file_info * fi_out, off_t offset_out, size_t size, int flags) diff --git a/netfs/fuse/fuseFiles.h b/netfs/fuse/fuseFiles.h index 37e3dec..087e1ee 100644 --- a/netfs/fuse/fuseFiles.h +++ b/netfs/fuse/fuseFiles.h @@ -11,6 +11,20 @@ namespace NetFS { void flush(); void wait() const; + struct BlockSizes { + size_t size1, sizeN, N; + auto operator<=>(const BlockSizes &) const = default; + [[nodiscard]] size_t total() const noexcept; + }; + + [[nodiscard]] static BlockSizes blockSizes(size_t total, size_t max) noexcept; + + [[nodiscard]] auto + blockSizes(size_t total) const noexcept + { + return blockSizes(total, bodyMaxSize); + } + FilePrxPtr remote; const std::string path; const int flags; diff --git a/netfs/unittests/testEdgeCases.cpp b/netfs/unittests/testEdgeCases.cpp index 5249aed..f47ecd4 100644 --- a/netfs/unittests/testEdgeCases.cpp +++ b/netfs/unittests/testEdgeCases.cpp @@ -1,6 +1,9 @@ #define BOOST_TEST_MODULE TestNetFSEdgeCases + +#include "fuseFiles.h" #include "mockDaemon.h" #include "mockFuse.h" +#include <boost/test/data/test_case.hpp> #include <boost/test/unit_test.hpp> #include <definedDirs.h> #include <random> @@ -121,6 +124,71 @@ BOOST_AUTO_TEST_CASE(manyThreads) BOOST_CHECK_EQUAL(failure, 0); } +namespace std { + ostream & + operator<<(ostream & s, const FuseMock::OpenFile::BlockSizes & b) + { + return s << '(' << b.size1 << '+' << b.sizeN << '*' << b.N << ')'; + } +} + +BOOST_AUTO_TEST_CASE(blockSizes) +{ + using BS = NetFS::FuseApp::OpenFile::BlockSizes; + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1, 1), (BS {1, 0, 0})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1, 5), (BS {1, 0, 0})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(5, 5), (BS {5, 0, 0})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(0, 1), (BS {0, 0, 0})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(5, 2), (BS {1, 2, 2})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(5, 3), (BS {2, 3, 1})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(29, 10), (BS {9, 10, 2})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(30, 10), (BS {0, 10, 3})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(31, 10), (BS {7, 8, 3})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(32, 10), (BS {5, 9, 3})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(33, 10), (BS {6, 9, 3})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(34, 10), (BS {7, 9, 3})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(35, 10), (BS {8, 9, 3})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(36, 10), (BS {6, 10, 3})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(37, 10), (BS {7, 10, 3})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(38, 10), (BS {8, 10, 3})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(39, 10), (BS {9, 10, 3})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(40, 10), (BS {0, 10, 4})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(41, 10), (BS {5, 9, 4})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1234, 100), (BS {94, 95, 12})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1235, 100), (BS {83, 96, 12})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1236, 100), (BS {84, 96, 12})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1237, 100), (BS {85, 96, 12})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1238, 100), (BS {86, 96, 12})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1239, 100), (BS {87, 96, 12})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1240, 100), (BS {88, 96, 12})); + BOOST_CHECK_EQUAL(NetFS::FuseApp::OpenFile::blockSizes(1241, 100), (BS {89, 96, 12})); +} + +BOOST_DATA_TEST_CASE(blockSizes_range, + boost::unit_test::data::xrange<size_t>(1, 200) + * boost::unit_test::data::make<size_t>({1, 5, 10, 16, 32, 256, 1024}), + total, max) +{ + const auto bs = NetFS::FuseApp::OpenFile::blockSizes(total, max); + BOOST_CHECK_LE(bs.size1, max); + BOOST_CHECK_LE(bs.sizeN, max); + BOOST_CHECK_EQUAL(bs.total(), total); + BOOST_CHECK_NE(bs.size1, bs.sizeN); +} + +BOOST_DATA_TEST_CASE(blockSizes_scatter, + (boost::unit_test::data::xrange<size_t>(1, 200, 17LU) + boost::unit_test::data::xrange<size_t>(1200, 1300, 3LU)) + * (boost::unit_test::data::xrange<size_t>(1, 100) + + boost::unit_test::data::xrange<size_t>(256, 4096, 256LU)), + total, max) +{ + const auto bs = NetFS::FuseApp::OpenFile::blockSizes(total, max); + BOOST_CHECK_LE(bs.size1, max); + BOOST_CHECK_LE(bs.sizeN, max); + BOOST_CHECK_EQUAL(bs.total(), total); + BOOST_CHECK_NE(bs.size1, bs.sizeN); +} + BOOST_AUTO_TEST_CASE(bigWritesAsync) { MockDaemonHost daemon(testEndpoint, {"--NetFSD.ConfigPath=" + (rootDir / "defaultDaemon.xml").string()}); |