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.cpp73
1 files changed, 42 insertions, 31 deletions
diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp
index b587809..222cab0 100644
--- a/netfs/fuse/fuseFiles.cpp
+++ b/netfs/fuse/fuseFiles.cpp
@@ -106,14 +106,47 @@ FuseApp::flush(const char *, struct fuse_file_info * fi)
}
}
+template<typename Rtn, typename F>
+inline
+Rtn
+FuseApp::waitOnWriteRangeAndThen(size_t s, off_t o, const OpenFilePtr & of, const F & f)
+{
+ const auto key = OpenFile::range(o, s);
+ while (true) {
+ std::unique_lock<decltype(of->_lock)> _l(of->_lock);
+ // Acquire operations to wait for
+ auto R = of->bg.equal_range(key);
+ if (R.first == R.second) {
+ // Perform operation
+ return f(key);
+ }
+ else {
+ // Wait for them whilst unlocked
+ _l.release()->unlock();
+ std::vector<Ice::AsyncResultPtr> overlap;
+ overlap.reserve(std::distance(R.first, R.second));
+ for (auto i = R.first; i != R.second; i++) {
+ overlap.push_back(i->second);
+ }
+ for (const auto & r : overlap) {
+ r->waitForCompleted();
+ }
+ // Cause this thread to yield so the callback can acquire _lock
+ usleep(0);
+ }
+ }
+}
+
int
FuseApp::read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi)
{
try {
auto of = getProxy<OpenFilePtr>(fi->fh);
- of->wait();
auto remote = of->remote;
- Buffer data = remote->read(o, s);
+ auto data = (fcr->Async) ?
+ waitOnWriteRangeAndThen<Buffer>(s, o, of, [o, s, &remote](const auto &){
+ return remote->read(o, s);
+ }) : remote->read(o, s);
memcpy(buf, &data.front(), data.size());
return data.size();
}
@@ -129,36 +162,14 @@ FuseApp::write(const char *, const char * buf, size_t s, off_t o, struct fuse_fi
auto of = getProxy<OpenFilePtr>(fi->fh);
auto remote = of->remote;
if (fcr->Async) {
- const auto key = OpenFile::range(o, s);
- while (true) {
- std::unique_lock<decltype(of->_lock)> _l(of->_lock);
- // Acquire operations to wait for
- std::vector<Ice::AsyncResultPtr> overlap;
- auto R = of->bg.equal_range(key);
- if (R.first == R.second) {
- // Begin write and store operation
- auto r = remote->begin_write(o, s, Buffer(buf, buf + s), [of,key](const Ice::AsyncResultPtr &) {
- ScopeLock(of->_lock) {
- of->bg.erase(key);
- }
- });
- of->bg.insert({key, r});
- break;
- }
- else {
- // Wait for them whilst unlocked
- _l.release()->unlock();
- overlap.reserve(std::distance(R.first, R.second));
- for (auto i = R.first; i != R.second; i++) {
- overlap.push_back(i->second);
- }
- for (const auto & r : overlap) {
- r->waitForCompleted();
+ waitOnWriteRangeAndThen<void>(s, o, of, [o, s, buf, &of, &remote](const auto & key){
+ auto r = remote->begin_write(o, s, Buffer(buf, buf + s), [of,key](const Ice::AsyncResultPtr &) {
+ ScopeLock(of->_lock) {
+ of->bg.erase(key);
}
- // Cause this thread to yield so the callback can acquire _lock
- usleep(0);
- }
- }
+ });
+ of->bg.insert({key, r});
+ });
}
else {
remote->write(o, s, Buffer(buf, buf + s));