diff options
Diffstat (limited to 'netfs/fuse/fuseFiles.cpp')
-rw-r--r-- | netfs/fuse/fuseFiles.cpp | 151 |
1 files changed, 56 insertions, 95 deletions
diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp index f47138d..fd313e5 100644 --- a/netfs/fuse/fuseFiles.cpp +++ b/netfs/fuse/fuseFiles.cpp @@ -5,13 +5,13 @@ #include <algorithm> #include <cstring> #include <entCache.h> -#include <functional> #include <future> -#include <iterator> #include <memory> #include <mutex> #include <numeric.h> #include <numeric> +#include <ranges> +#include <span> #include <utility> #include <vector> @@ -164,74 +164,61 @@ namespace NetFS { } } - namespace { - void - blockSizeIterate(FuseApp::OpenFile::BlockSizes blockSizes, auto && callback) - { - if (blockSizes.size1) { - callback(blockSizes.size1); - } - while (blockSizes.countN--) { - callback(blockSizes.sizeN); - } - } - } - int FuseApp::read(const char *, char * buf, size_t size, off_t offset, struct fuse_file_info * fileInfo) { try { + const std::span out(buf, size); using BackgroundOps = std::vector<std::promise<int>>; - auto cpy = [buf](off_t blockOffset, const auto && data) -> int { - std::copy(data.begin(), data.end(), buf + blockOffset); + const auto cpy = [out](off_t blockOffset, const auto && data) -> int { + std::ranges::copy(data, out.begin() + blockOffset); return safe {data.size()}; }; - auto collateTotal = [](auto && ops) { + const auto collateTotal = [](auto && ops) { return std::accumulate(ops.begin(), ops.end(), 0, [](auto && total, auto & operation) { return total += operation.get_future().get(); }); }; auto openFile = getProxy<OpenFilePtr>(fileInfo->fh); auto remote = openFile->remote; - auto blockSizes = openFile->blockSizes(size); if (fcr->Async) { - BackgroundOps ops(blockSizes.count()); - blockSizeIterate(blockSizes, - [&offset, &openFile, &remote, blockOffset = 0U, &cpy, opIter = ops.begin()]( - safe<size_t> blockSize) mutable { - waitOnWriteRangeAndThen(blockSize, offset, openFile, - [thisOp = opIter++, offset, blockOffset, blockSize, &remote, &cpy](const auto &) { + const auto blocks = out | std::views::chunk(openFile->bodyMaxSize); + BackgroundOps ops(blocks.size()); + std::ranges::for_each( + blocks, [offset, &openFile, &remote, &cpy, opIter = ops.begin(), out](auto && block) mutable { + waitOnWriteRangeAndThen(block.size(), offset, openFile, + [thisOp = opIter++, offset, &remote, &cpy, block, out](const auto &) { + const auto outPosition = block.begin() - out.begin(); + const auto position = offset + outPosition; return remote->readAsync( - offset, blockSize, - [cpy, thisOp, blockOffset](auto && resultBuf) { + position, safe(block.size()), + [cpy, thisOp, outPosition](auto && resultBuf) { thisOp->set_value( - cpy(blockOffset, std::forward<Ice::ByteSeq>(resultBuf))); + cpy(outPosition, std::forward<Ice::ByteSeq>(resultBuf))); }, [thisOp](auto error) { thisOp->set_exception(std::move(error)); }); }); - offset += blockSize; - blockOffset += blockSize; }); return collateTotal(ops); } if (openFile->bodyMaxSize < size) { - BackgroundOps ops(blockSizes.count()); - blockSizeIterate(blockSizes, - [&offset, &remote, blockOffset = 0U, &cpy, opIter = ops.begin()]( - safe<size_t> blockSize) mutable { + const auto blocks = out | std::views::chunk(openFile->bodyMaxSize); + BackgroundOps ops(blocks.size()); + std::ranges::for_each( + blocks, [offset, &remote, out, &cpy, opIter = ops.begin()](auto && block) mutable { auto thisOp = opIter++; + const auto outPosition = block.begin() - out.begin(); + const auto position = offset + outPosition; remote->readAsync( - offset, blockSize, - [cpy, thisOp, blockOffset](auto && resultBuf) { - thisOp->set_value(cpy(blockOffset, std::forward<Ice::ByteSeq>(resultBuf))); + position, safe(block.size()), + [cpy, thisOp, outPosition](auto && resultBuf) { + thisOp->set_value(cpy(outPosition, std::forward<Ice::ByteSeq>(resultBuf))); }, [thisOp](auto error) { thisOp->set_exception(std::move(error)); }); - offset += blockSize; - blockOffset += blockSize; }); return collateTotal(ops); } @@ -245,44 +232,47 @@ namespace NetFS { int FuseApp::write(const char *, const char * buf, size_t size, off_t offset, struct fuse_file_info * fileInfo) { + static auto toBuffer = [](auto block) { + return std::make_pair(std::to_address(block.begin()), std::to_address(block.end())); + }; try { auto openFile = getProxy<OpenFilePtr>(fileInfo->fh); auto remote = openFile->remote; - auto bytes = reinterpret_cast<const ::Ice::Byte *>(buf); + const std::span bytes {reinterpret_cast<const ::Ice::Byte *>(buf), size}; if (fcr->Async) { - blockSizeIterate( - openFile->blockSizes(size), [&bytes, &offset, &remote, &openFile](safe<size_t> blockSize) { - waitOnWriteRangeAndThen(blockSize, offset, openFile, - [offset, blockSize, bytes, &openFile, remote](const auto & key) { - auto p = std::make_shared<OpenFile::WriteState>(); - openFile->bg.insert({key, p}); - remote->writeAsync( - offset, blockSize, std::make_pair(bytes, bytes + blockSize), - [p, openFile, key]() { - p->promise.set_value(); - ScopeLock(openFile->mutex) { - openFile->bg.erase(key); - } - }, - [p, openFile](auto error) { - p->promise.set_exception(std::move(error)); - }); - }); - bytes += blockSize; - offset += blockSize; - }); + const auto blocks = bytes | std::views::chunk(openFile->bodyMaxSize); + std::ranges::for_each(blocks, [&remote, bytes, offset, &openFile](auto && block) { + const auto position = offset + (block.begin() - bytes.begin()); + waitOnWriteRangeAndThen( + block.size(), position, openFile, [position, block, &openFile, remote](const auto & key) { + auto pendingWrite = std::make_shared<OpenFile::WriteState>(); + openFile->bg.insert({key, pendingWrite}); + remote->writeAsync( + position, safe(block.size()), toBuffer(block), + [pendingWrite, openFile, key]() { + pendingWrite->promise.set_value(); + ScopeLock(openFile->mutex) { + openFile->bg.erase(key); + } + }, + [pendingWrite, openFile](auto error) { + pendingWrite->promise.set_exception(std::move(error)); + }); + }); + }); } else if (openFile->bodyMaxSize < size) { + const auto blocks = bytes | std::views::chunk(openFile->bodyMaxSize); std::vector<std::future<void>> ops; - blockSizeIterate(openFile->blockSizes(size), [&ops, &bytes, &offset, &remote](safe<size_t> blockSize) { - ops.emplace_back(remote->writeAsync(offset, blockSize, std::make_pair(bytes, bytes + blockSize))); - bytes += blockSize; - offset += blockSize; + ops.reserve(blocks.size()); + std::ranges::transform(blocks, std::back_inserter(ops), [&remote, bytes, offset](auto && block) { + const auto position = offset + (block.begin() - bytes.begin()); + return remote->writeAsync(position, safe(block.size()), toBuffer(block)); }); std::ranges::for_each(ops, &std::future<void>::get); } else { - remote->write(offset, safe {size}, std::make_pair(bytes, bytes + size)); + remote->write(offset, safe {size}, toBuffer(bytes)); } return safe {size}; } @@ -291,35 +281,6 @@ 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 {.size1 = total, .sizeN = 0, .countN = 0}; - } - if (total % max == 0) { // Simplish case, multiples of max - return {.size1 = 0, .sizeN = max, .countN = total / max}; - } - const auto blocks = (total / max); - const auto blockSize = (total / (blocks + 1)) + 1; - const auto batchTotal = blockSize * blocks; - const auto remainder = total - batchTotal; - - return {.size1 = remainder, .sizeN = blockSize, .countN = blocks}; - } - - size_t - FuseApp::OpenFile::BlockSizes::total() const noexcept - { - return size1 + (sizeN * countN); - } - - size_t - FuseApp::OpenFile::BlockSizes::count() const noexcept - { - return countN + (size1 ? 1 : 0); - } - ssize_t FuseApp::copy_file_range(const char *, struct fuse_file_info * fileInfoIn, off_t offsetIn, const char *, struct fuse_file_info * fileInfoOut, off_t offsetOut, size_t size, int flags) |