summaryrefslogtreecommitdiff
path: root/netfs/fuse/fuseFiles.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netfs/fuse/fuseFiles.cpp')
-rw-r--r--netfs/fuse/fuseFiles.cpp151
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)