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.cpp59
1 files changed, 36 insertions, 23 deletions
diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp
index 4c93d56..eb80531 100644
--- a/netfs/fuse/fuseFiles.cpp
+++ b/netfs/fuse/fuseFiles.cpp
@@ -23,7 +23,7 @@ FuseApp::OpenFile::wait() const
{
SharedLock(_lock);
for (const auto & w : bg) {
- w->waitForCompleted();
+ w.second->waitForCompleted();
}
}
@@ -32,29 +32,18 @@ FuseApp::OpenFile::flush()
{
Lock(_lock);
while (!bg.empty()) {
- auto w = bg.front();
- bg.pop_front();
+ auto wi = bg.begin();
+ auto w = wi->second;
+ bg.erase(w);
// bg operations are void, so no need to actually get the return value
w->throwLocalException();
}
}
-void
-FuseApp::OpenFile::nonBlockingFlush()
+FuseApp::OpenFile::BGs::interval_type
+FuseApp::OpenFile::range(off_t o, size_t s)
{
- boost::unique_lock<boost::shared_mutex> lock(_lock, boost::try_to_lock);
- if (lock.owns_lock()) {
- for (auto wi = bg.begin(); wi != bg.end(); ) {
- auto w = *wi;
- if (w->isCompleted()) {
- wi = bg.erase(wi);
- w->throwLocalException();
- }
- else {
- wi++;
- }
- }
- }
+ return OpenFile::BGs::interval_type::right_open(o, o + s);
}
int
@@ -138,15 +127,39 @@ FuseApp::write(const char *, const char * buf, size_t s, off_t o, struct fuse_fi
try {
auto of = getProxy<OpenFilePtr>(fi->fh);
auto remote = of->remote;
- auto r = remote->begin_write(o, s, Buffer(buf, buf + s));
if (fcr->Async) {
- ScopeLock(of->_lock) {
- of->bg.push_back(r);
+ const auto key = OpenFile::range(s, o);
+ while (true) {
+ ScopeLock(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});
+ return s;
+ }
+ else {
+ // Wait for them whilst unlocked
+ of->_lock.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();
+ }
+ }
+ }
}
- of->nonBlockingFlush();
}
else {
- r->throwLocalException();
+ remote->write(o, s, Buffer(buf, buf + s));
}
return s;
}