diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2022-05-07 17:04:20 +0100 | 
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2022-05-07 17:17:56 +0100 | 
| commit | 5b63feaf3abd8b39587a826524fccf344b71658b (patch) | |
| tree | 0a6b91e28152ca98ce301d91ba6faec8b203353f | |
| parent | Simplify blockSize iteration (diff) | |
| download | netfs-5b63feaf3abd8b39587a826524fccf344b71658b.tar.bz2 netfs-5b63feaf3abd8b39587a826524fccf344b71658b.tar.xz netfs-5b63feaf3abd8b39587a826524fccf344b71658b.zip  | |
Fix and test performing large reads
Adds scope to large read/write and extends to test at multiple offsets.
| -rw-r--r-- | netfs/fuse/fuseFiles.cpp | 41 | ||||
| -rw-r--r-- | netfs/unittests/testEdgeCases.cpp | 52 | 
2 files changed, 72 insertions, 21 deletions
diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp index c1709cd..c50dcf1 100644 --- a/netfs/fuse/fuseFiles.cpp +++ b/netfs/fuse/fuseFiles.cpp @@ -1,10 +1,12 @@  #include "fuseFiles.h"  #include "fuseApp.impl.h"  #include "lockHelpers.h" +#include <Ice/BuiltinSequences.h>  #include <cstring>  #include <entCache.h>  #include <mutex>  #include <numeric.h> +#include <numeric>  namespace NetFS {  	FuseApp::OpenFile::WriteState::WriteState() : future(promise.get_future().share()) { } @@ -167,20 +169,47 @@ namespace NetFS {  	FuseApp::read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi)  	{  		try { -			auto cpy = [buf](const auto && data) -> int { -				std::copy(data.begin(), data.end(), buf); +			struct bgOp { +				bgOp(int o, std::future<Ice::ByteSeq> r) : offset {o}, response {std::move(r)} { } +				int offset; +				std::future<Ice::ByteSeq> response; +			}; +			auto cpy = [buf](off_t blockOffset, const auto && data) -> int { +				std::copy(data.begin(), data.end(), buf + blockOffset);  				return safe {data.size()};  			};  			auto of = getProxy<OpenFilePtr>(fi->fh);  			auto remote = of->remote; +			auto blockSizes = of->blockSizes(s);  			if (fcr->Async) { -				auto p = waitOnWriteRangeAndThen<std::future<Buffer>>(s, o, of, [o, s, &remote](const auto &) { -					return remote->readAsync(o, safe {s}); +				std::vector<bgOp> ops; +				blockSizeIterate( +						blockSizes, [&ops, &o, &of, &remote, blockOffset = 0U](safe<size_t> blockSize) mutable { +							ops.emplace_back(blockOffset, +									waitOnWriteRangeAndThen<std::future<Buffer>>( +											blockSize, o, of, [o, blockSize, &remote](const auto &) { +												return remote->readAsync(o, blockSize); +											})); +							o += blockSize; +							blockOffset += blockSize; +						}); +				return std::accumulate(ops.begin(), ops.end(), 0, [cpy](auto && total, auto & op) { +					return total += cpy(op.offset, op.response.get()); +				}); +			} +			else if (of->bodyMaxSize < s) { +				std::vector<bgOp> ops; +				blockSizeIterate(blockSizes, [&ops, &o, &remote, blockOffset = 0U](safe<size_t> blockSize) mutable { +					ops.emplace_back(blockOffset, remote->readAsync(o, blockSize)); +					o += blockSize; +					blockOffset += blockSize; +				}); +				return std::accumulate(ops.begin(), ops.end(), 0, [cpy](auto && total, auto & op) { +					return total += cpy(op.offset, op.response.get());  				}); -				return cpy(p.get());  			}  			else { -				return cpy(remote->read(o, safe {s})); +				return cpy(0, remote->read(o, safe {s}));  			}  		}  		catch (SystemError & e) { diff --git a/netfs/unittests/testEdgeCases.cpp b/netfs/unittests/testEdgeCases.cpp index c2e101f..0c78084 100644 --- a/netfs/unittests/testEdgeCases.cpp +++ b/netfs/unittests/testEdgeCases.cpp @@ -6,6 +6,7 @@  #include <boost/test/data/test_case.hpp>  #include <boost/test/unit_test.hpp>  #include <definedDirs.h> +#include <fcntl.h>  #include <fileUtils.h>  const std::string testEndpoint("tcp -h localhost -p 12014"); @@ -189,24 +190,45 @@ BOOST_DATA_TEST_CASE(blockSizes_scatter,  	BOOST_CHECK_NE(bs.size1, bs.sizeN);  } -BOOST_DATA_TEST_CASE(bigWrites, +BOOST_DATA_TEST_CASE(bigWritesAndReads,  		boost::unit_test::data::make({"defaultFuseNoAsync.xml", "defaultFuse.xml"}) -				* boost::unit_test::data::xrange<size_t>(1024UL * 100UL, 4096UL * 1024UL, 512UL * 1024UL), -		config, size) +				* boost::unit_test::data::xrange<size_t>(1024UL * 100UL, 4096UL * 1024UL, 512UL * 1024UL) +				* boost::unit_test::data::make<off_t>(0, 317, 4096UL * 1024UL), +		config, size, offset)  {  	MockDaemonHost daemon(testEndpoint, {"--NetFSD.ConfigPath=" + (rootDir / "defaultDaemon.xml").string()});  	FuseMockHost fuse(testEndpoint, {(rootDir / config).string() + ":testvol", (rootDir / "test").string()}); -	const auto buf = FuseMock::genRandomData(size); -	fuse_file_info fi {}; -	fi.flags = O_RDWR; -	auto fd = fuse.fuse->create("/big", 0600, &fi); -	BOOST_REQUIRE_GE(fd, 0); -	BOOST_REQUIRE_NE(fi.fh, 0); -	BOOST_CHECK_EQUAL(buf.size(), fuse.fuse->write("/big", buf.data(), buf.size(), 0, &fi)); -	BOOST_REQUIRE_EQUAL(0, fuse.fuse->release("/big", &fi)); - -	AdHoc::FileUtils::MemMap mm(daemon.TestExportRoot / "big"); -	const auto file {mm.sv()}; -	BOOST_CHECK_EQUAL_COLLECTIONS(buf.begin(), buf.end(), file.begin(), file.end()); +	{ +		const auto buf = FuseMock::genRandomData(size); +		{ +			fuse_file_info fi {}; +			fi.flags = O_RDWR; +			auto fd = fuse.fuse->create("/big", 0600, &fi); +			BOOST_REQUIRE_GE(fd, 0); +			BOOST_REQUIRE_NE(fi.fh, 0); +			BOOST_REQUIRE_EQUAL(buf.size(), fuse.fuse->write("/big", buf.data(), buf.size(), offset, &fi)); +			BOOST_REQUIRE_EQUAL(0, fuse.fuse->release("/big", &fi)); +		} + +		AdHoc::FileUtils::MemMap mm(daemon.TestExportRoot / "big"); +		const auto file {mm.sv()}; +		BOOST_CHECK_EQUAL_COLLECTIONS(buf.begin(), buf.end(), file.begin() + offset, file.end()); +	} +	{ +		auto buf = FuseMock::genRandomData(size); +		{ +			fuse_file_info fi {}; +			fi.flags = O_RDONLY; +			auto fd = fuse.fuse->open("/big", &fi); +			BOOST_REQUIRE_GE(fd, 0); +			BOOST_REQUIRE_NE(fi.fh, 0); +			BOOST_REQUIRE_EQUAL(buf.size(), fuse.fuse->read("/big", buf.data(), buf.size(), offset, &fi)); +			BOOST_REQUIRE_EQUAL(0, fuse.fuse->release("/big", &fi)); +		} + +		AdHoc::FileUtils::MemMap mm(daemon.TestExportRoot / "big"); +		const auto file {mm.sv()}; +		BOOST_CHECK_EQUAL_COLLECTIONS(buf.begin(), buf.end(), file.begin() + offset, file.end()); +	}  }  | 
