summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--netfs/fuse/fuseFiles.cpp25
-rw-r--r--netfs/fuse/fuseFiles.h14
-rw-r--r--netfs/unittests/testEdgeCases.cpp68
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()});