Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
W
wendelin.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Joshua
wendelin.core
Commits
a41fe05a
Commit
a41fe05a
authored
Mar 02, 2020
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
d41689f6
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
35 additions
and
35 deletions
+35
-35
wcfs/client/wcfs.cpp
wcfs/client/wcfs.cpp
+34
-34
wcfs/client/wcfs.h
wcfs/client/wcfs.h
+1
-1
No files found.
wcfs/client/wcfs.cpp
View file @
a41fe05a
...
...
@@ -257,10 +257,10 @@ error _Conn::close() {
};
bool
alreadyClosed
=
false
;
wconn
.
_
m
u
.
Lock
();
wconn
.
_
filehM
u
.
Lock
();
alreadyClosed
=
(
wconn
.
_downErr
==
errConnClosed
);
wconn
.
_downErr
=
errConnClosed
;
wconn
.
_
m
u
.
Unlock
();
wconn
.
_
filehM
u
.
Unlock
();
if
(
alreadyClosed
)
return
nil
;
...
...
@@ -279,9 +279,9 @@ error _Conn::close() {
// NOTE after file is closed mappings could continue to survive, but we can no
// longer maintain consistent view. For this reason we change mappings to
// something that gives EFAULT on access. XXX implement
wconn
.
_
m
u
.
Lock
();
wconn
.
_
filehM
u
.
Lock
();
defer
([
&
]()
{
wconn
.
_
m
u
.
Unlock
();
wconn
.
_
filehM
u
.
Unlock
();
});
// XXX f locking
...
...
@@ -319,13 +319,13 @@ error _Conn::_pinner(context::Context ctx) {
// mark the connection non-operational if the pinner fails
// XXX deadlock wrt resync? (who read-locks wconn.mu)
// XXX -> mu -> downMu ?
wconn
.
_
m
u
.
Lock
();
// XXX locking ok? -> merge into below where lock is held?
wconn
.
_
filehM
u
.
Lock
();
// XXX locking ok? -> merge into below where lock is held?
if
(
wconn
.
_downErr
==
nil
)
{
wconn
.
_downErr
=
fmt
::
errorf
(
"no longer operational due to: %w"
,
err
!=
nil
?
err
:
fmt
::
errorf
(
"pinner exit"
));
// XXX make all fileh and mapping invalid.
}
wconn
.
_
m
u
.
Unlock
();
wconn
.
_
filehM
u
.
Unlock
();
return
err
;
}
...
...
@@ -342,9 +342,9 @@ error _Conn::__pinner(context::Context ctx) {
if
(
err
!=
nil
)
{
// it is ok if we receive EOF due to us (client) closing the connection
if
(
err
==
io
::
EOF_
)
{
wconn
.
_
m
u
.
RLock
();
wconn
.
_
filehM
u
.
RLock
();
err
=
(
wconn
.
_downErr
==
errConnClosed
)
?
nil
:
io
::
ErrUnexpectedEOF
;
wconn
.
_
m
u
.
RUnlock
();
wconn
.
_
filehM
u
.
RUnlock
();
}
return
E
(
err
);
}
...
...
@@ -388,19 +388,19 @@ error _Conn::__pin1(PinReq *req) {
});
// XXX deadlock wrt Conn.resync which locks wconn.mu and does "watch" ?
wconn
.
_
m
u
.
RLock
();
wconn
.
_
filehM
u
.
RLock
();
// XXX +incref f, so that simultaneous close does not remove f from wconn.filehTab ?
// XXX or just make FileH.close lock f too to synchronize with pinner?
tie
(
f
,
ok
)
=
wconn
.
_filehTab
.
get_
(
req
->
foid
);
if
(
!
ok
)
{
wconn
.
_
m
u
.
RUnlock
();
wconn
.
_
filehM
u
.
RUnlock
();
// why wcfs sent us this update?
return
fmt
::
errorf
(
"unexpected pin: f<%s> not watched"
,
v
(
req
->
foid
));
}
// XXX <- f._openReady ?
wconn
.
_
m
u
.
RUnlock
();
// XXX maybe `f.mu.lock() -> wconn.mu.unlock()` to avoid race with FileH close?
wconn
.
_
filehM
u
.
RUnlock
();
// XXX maybe `f.mu.lock() -> wconn.mu.unlock()` to avoid race with FileH close?
f
->
_mu
.
lock
();
defer
([
&
]()
{
f
->
_mu
.
unlock
();
...
...
@@ -441,7 +441,7 @@ error _Conn::__pin1(PinReq *req) {
// on error don't need to continue with other mappings - all fileh and
// all mappings become marked invalid on pinner failure.
// XXX all call wconn._down from here under wconn._
m
u lock?
// XXX all call wconn._down from here under wconn._
filehM
u lock?
if
(
err
!=
nil
)
return
err
;
...
...
@@ -485,13 +485,13 @@ error _Conn::resync(zodb::Tid at) {
// particular _pinner_, from running and mutating files and mappings.
//
// NOTE we'll relock atMu as R in the second part of resync, so we prelock
// wconn._
m
u.R as well while under atMu.W, to be sure that set of opened
// wconn._
filehM
u.R as well while under atMu.W, to be sure that set of opened
// files stays the same during whole resync.
bool
atMuWLocked
=
true
;
wconn
.
_atMu
.
Lock
();
wconn
.
_
m
u
.
RLock
();
wconn
.
_
filehM
u
.
RLock
();
defer
([
&
]()
{
wconn
.
_
m
u
.
RUnlock
();
wconn
.
_
filehM
u
.
RUnlock
();
if
(
atMuWLocked
)
wconn
.
_atMu
.
Unlock
();
else
...
...
@@ -511,7 +511,7 @@ error _Conn::resync(zodb::Tid at) {
// set new wconn.at early, so that e.g. Conn.open running simultaneously
// to second part of resync (see below) uses new at.
// XXX no need since wconn._
m
u is locked? -> no - it is *needed* after wconn.mu became RWMutex
// XXX no need since wconn._
filehM
u is locked? -> no - it is *needed* after wconn.mu became RWMutex
wconn
.
at
=
at
;
// go through all files opened under wconn and pre-adjust their mappings
...
...
@@ -569,15 +569,15 @@ error _Conn::resync(zodb::Tid at) {
// - we need to hold atMu.R to avoid race wrt e.g. other resync which changes at.
// - we cannot just do regular `atMu.Unlock + atMu.RLock()` because then
// there is e.g. a race window in between Unlock and RLock where wconn.at can be changed.
// XXX also deadlock, because it will become wconn._
m
u.lock + wconn._atMu lock
// XXX also deadlock, because it will become wconn._
filehM
u.lock + wconn._atMu lock
//
// Now other calls, e.g. Conn.open, can be running simultaneously to us,
// but since we already set wconn.at to new value it is ok. For example
// Conn.open, for not-yet-opened file, will use new at to send "watch".
// XXX ^^^ not possible since wconn._
m
u is locked ?
// -> no, possible, wconn._
m
u became RWMutex
// XXX ^^^ not possible since wconn._
filehM
u is locked ?
// -> no, possible, wconn._
filehM
u became RWMutex
//
// XXX we are still holding wconn._
m
u.R, so wconn._filehTab is the
// XXX we are still holding wconn._
filehM
u.R, so wconn._filehTab is the
// same as in previous pass above.
wconn
.
_atMu
.
UnlockToRLock
();
atMuWLocked
=
false
;
...
...
@@ -592,7 +592,7 @@ error _Conn::resync(zodb::Tid at) {
zodb
::
Oid
foid
=
fit
.
first
;
FileH
f
=
fit
.
second
;
// XXX locking ok? (protected by wconn._
m
u ?)
// XXX locking ok? (protected by wconn._
filehM
u ?)
if
(
f
->
_state
!=
_FileHOpened
)
continue
;
...
...
@@ -623,11 +623,11 @@ pair<FileH, error> _Conn::open(zodb::Oid foid) {
xerr
::
Contextf
E
(
"%s: open f<%s>"
,
v
(
wconn
),
v
(
foid
));
wconn
.
_
m
u
.
Lock
();
wconn
.
_
filehM
u
.
Lock
();
if
(
wconn
.
_downErr
!=
nil
)
{
err
=
wconn
.
_downErr
;
wconn
.
_
m
u
.
Unlock
();
wconn
.
_
filehM
u
.
Unlock
();
return
make_pair
(
nil
,
E
(
err
));
}
...
...
@@ -643,7 +643,7 @@ retry:
}
else
{
closing
=
true
;
}
wconn
.
_
m
u
.
Unlock
();
wconn
.
_
filehM
u
.
Unlock
();
// if the file was closing|closed, we should wait for the close to
// complete and retry the open.
...
...
@@ -663,7 +663,7 @@ retry:
return
make_pair
(
f
,
nil
);
}
// create "opening" FileH entry and perform open with wconn._
m
u released
// create "opening" FileH entry and perform open with wconn._
filehM
u released
// NOTE wconn._atMu.R is still held because FileH._open relies on wconn.at being stable.
f
=
adoptref
(
new
_FileH
());
f
->
wconn
=
newref
(
&
wconn
);
...
...
@@ -680,9 +680,9 @@ retry:
bool
retok
=
false
;
wconn
.
_filehTab
[
foid
]
=
f
;
defer
([
&
]()
{
wconn
.
_
m
u
.
Lock
();
wconn
.
_
filehM
u
.
Lock
();
if
(
wconn
.
_filehTab
.
get
(
foid
)
!=
f
)
{
wconn
.
_
m
u
.
Unlock
();
wconn
.
_
filehM
u
.
Unlock
();
panic
(
"BUG: wconn.open: wconn.filehTab[foid] mutated while file open was in progress"
);
}
if
(
!
retok
)
{
...
...
@@ -691,10 +691,10 @@ retry:
}
else
{
f
->
_state
=
_FileHOpened
;
}
wconn
.
_
m
u
.
Unlock
();
wconn
.
_
filehM
u
.
Unlock
();
f
->
_openReady
.
close
();
});
wconn
.
_
m
u
.
Unlock
();
wconn
.
_
filehM
u
.
Unlock
();
f
->
_openErr
=
f
->
_open
();
if
(
f
->
_openErr
!=
nil
)
...
...
@@ -760,9 +760,9 @@ error _FileH::close() {
Conn
wconn
=
fileh
.
wconn
;
wconn
->
_atMu
.
RLock
();
wconn
->
_
mu
.
Lock
()
wconn
->
_
filehMu
.
Lock
();
defer
([
&
]()
{
wconn
->
_
m
u
.
Unlock
();
wconn
->
_
filehM
u
.
Unlock
();
wconn
->
_atMu
.
RUnlock
();
});
...
...
@@ -785,7 +785,7 @@ error _FileH::close() {
// unlock wconn.mu to stop watching outside of this lock.
// we'll relock it again before updating wconn.filehTab.
wconn
->
_
m
u
.
Unlock
();
wconn
->
_
filehM
u
.
Unlock
();
error
err
,
eret
;
...
...
@@ -806,8 +806,8 @@ error _FileH::close() {
reterr1
(
fmt
::
errorf
(
"unwatch: %s"
,
v
(
ack
)));
// relock wconn._
m
u again and remove fileh from wconn._filehTab
wconn
->
_
m
u
.
Lock
();
// relock wconn._
filehM
u again and remove fileh from wconn._filehTab
wconn
->
_
filehM
u
.
Lock
();
if
(
wconn
->
_filehTab
.
get
(
fileh
.
foid
).
_ptr
()
!=
&
fileh
)
panic
(
"BUG: fileh.close: wconn.filehTab[fileh.foid] != fileh"
);
wconn
->
_filehTab
.
erase
(
fileh
.
foid
);
...
...
wcfs/client/wcfs.h
View file @
a41fe05a
...
...
@@ -181,7 +181,7 @@ struct _Conn : object {
sync
::
RWMutex
_atMu
;
zodb
::
Tid
at
;
sync
::
RWMutex
_
mu
;
// _atMu.W | _atMu.R + _mu XXX -> _filehMu ? -> y
sync
::
RWMutex
_
filehMu
;
// _atMu.W | _atMu.R + _filehMu
error
_downErr
;
// !nil if connection is closed or no longer operational
dict
<
zodb
::
Oid
,
FileH
>
_filehTab
;
// {} foid -> fileh
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment