Commit 0e6afd21 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 9c3a2154
...@@ -491,7 +491,7 @@ type Head struct { ...@@ -491,7 +491,7 @@ type Head struct {
// it is also kept rlocked by OS cache uploaders (see BigFile.uploadBlk) // it is also kept rlocked by OS cache uploaders (see BigFile.uploadBlk)
// with additional locking protocol to avoid deadlocks (see below for // with additional locking protocol to avoid deadlocks (see below for
// pauseOSCacheUpload + ...). // pauseOSCacheUpload + ...).
zconnMu sync.RWMutex zconnMu sync.RWMutex // XXX -> zheadMu ?
zconn *ZConn // for head/ zwatcher resyncs head.zconn; others only read zconn objects. zconn *ZConn // for head/ zwatcher resyncs head.zconn; others only read zconn objects.
// zwatcher signals to uploadBlk to pause/continue uploads to OS cache to avoid deadlocks. // zwatcher signals to uploadBlk to pause/continue uploads to OS cache to avoid deadlocks.
...@@ -505,7 +505,6 @@ type Head struct { ...@@ -505,7 +505,6 @@ type Head struct {
// head/watch opens // head/watch opens
// XXX protected by ... head.zconnMu ? // XXX protected by ... head.zconnMu ?
// XXX -> watchTab?
wlinkTab map[*WatchLink]struct{} wlinkTab map[*WatchLink]struct{}
} }
...@@ -1313,28 +1312,34 @@ retry: ...@@ -1313,28 +1312,34 @@ retry:
// pin makes sure that file[blk] on client side is the same as of @rev state. // pin makes sure that file[blk] on client side is the same as of @rev state.
// //
// rev must be ≤ w.at, and there must be no rev_next: rev < rev_next ≤ w.at. // rev = zodb.TidMax means @head; otherwise rev must be ≤ w.at and there must
// be no rev_next changing file[blk]: rev < rev_next ≤ w.at.
// //
// XXX error - when? or close watch on any error? // XXX error - when? or close watch on any error?
func (w *Watch) pin(ctx context.Context, blk int64, rev zodb.Tid) (err error) { func (w *Watch) pin(ctx context.Context, blk int64, rev zodb.Tid) (err error) {
foid := w.file.zfile.POid() foid := w.file.zfile.POid()
defer xerr.Contextf(&err, "f<%s>: watch%d: pin #%d @%s", foid, w.link.id, blk, rev) revstr := rev.String()
if rev == zodb.TidMax {
revstr = "head"
}
defer xerr.Contextf(&err, "f<%s>: wlink%d: pin #%d @%s", foid, w.link.id, blk, revstr)
// XXX locking? // XXX locking?
// XXX simultaneous calls? // XXX simultaneous calls?
// XXX rev=inf -> unpin to head
if rev > w.at { if !(rev == zodb.TidMax || rev <= w.at) {
panicf("f<%s>: watch%d: pin #%d @%s: watch.at (%s) < rev", panicf("f<%s>: wlink%d: pin #%d @%s: watch.at (%s) < rev",
foid, w.link.id, blk, rev, w.at) foid, w.link.id, blk, rev, w.at)
} }
if w.pinned[blk] == rev { if w.pinned[blk] == rev {
// XXX pinned has to be invalidated when w.at↑ if rev == zodb.TidMax {
return // already pinned panicf("f<%s>: wlink%d: pinned[#%d] = @head", foid, w.link.id, blk)
}
return // already pinned XXX for simultaneous calls?
} }
ack, err := w.link.sendReq(ctx, fmt.Sprintf("pin %s #%d @%s", foid, blk, rev)) ack, err := w.link.sendReq(ctx, fmt.Sprintf("pin %s #%d @%s", foid, blk, revstr))
if err != nil { if err != nil {
return err return err
} }
...@@ -1343,7 +1348,12 @@ func (w *Watch) pin(ctx context.Context, blk int64, rev zodb.Tid) (err error) { ...@@ -1343,7 +1348,12 @@ func (w *Watch) pin(ctx context.Context, blk int64, rev zodb.Tid) (err error) {
return fmt.Errorf("expect %q; got %q", "ack", ack) return fmt.Errorf("expect %q; got %q", "ack", ack)
} }
if rev == zodb.TidMax {
delete(w.pinned, blk)
} else {
w.pinned[blk] = rev w.pinned[blk] = rev
}
return nil return nil
} }
...@@ -1402,12 +1412,12 @@ func (wlink *WatchLink) setupWatch(ctx context.Context, foid zodb.Oid, at zodb.T ...@@ -1402,12 +1412,12 @@ func (wlink *WatchLink) setupWatch(ctx context.Context, foid zodb.Oid, at zodb.T
// blocks. If we don't, we can miss to send pin for a freshly read // blocks. If we don't, we can miss to send pin for a freshly read
// block which could have revision > w.at . // block which could have revision > w.at .
toPin := map[int64]zodb.Tid{} // blk -> @rev // pin all tracked file blocks that were changed in (at, head] range.
// XXX locking // XXX locking
// pin all tracked file blocks that were changed in (at, head] range toPin := map[int64]zodb.Tid{} // blk -> @rev
// XXX blk in w.pinned; blk not in δ -> unpin to head
f := w.file f := w.file
for _, δfile := range bfdir.δFtail.SliceByFileRev(f, at, headAt) { for _, δfile := range bfdir.δFtail.SliceByFileRev(f, at, headAt) {
for blk := range δfile.Blocks { for blk := range δfile.Blocks {
...@@ -1416,11 +1426,20 @@ func (wlink *WatchLink) setupWatch(ctx context.Context, foid zodb.Oid, at zodb.T ...@@ -1416,11 +1426,20 @@ func (wlink *WatchLink) setupWatch(ctx context.Context, foid zodb.Oid, at zodb.T
continue continue
} }
//toPin[blk], _ = f.LastBlkRev(ctx, blk, at) toPin[blk], _ = f.LastBlkRev(ctx, blk, at)
pinrev, _ := f.LastBlkRev(ctx, blk, at) }
if w.pinned[blk] != pinrev { // XXX locking
toPin[blk] = pinrev
} }
// if a block was previously pinned, but ∉ δ(at, head] -> unpin it to head.
for blk, pinPrev := range w.pinned { // XXX locking
pinNew, pinning := toPin[blk]
if !pinning {
toPin[blk] = zodb.TidMax // @head
}
// don't bother to spawn .pin goroutines if pin revision is the same
if pinPrev == pinNew {
delete(toPin, blk)
} }
} }
......
...@@ -596,7 +596,7 @@ class tSrvReq: ...@@ -596,7 +596,7 @@ class tSrvReq:
# _pinAt returns which blocks needs to be pinned for zf@at. # _pinAt returns which blocks needs to be pinned for zf@at.
# #
# it does not take into account whether blocks are in cache or not and computes # it does not take into account whether blocks are in cache or not and computes
# pin from all changes. # pin from all changes. XXX desired behaviour?
@func(tWatch) @func(tWatch)
def _pinAt(w, zf, at): # -> pin = {} blk -> rev def _pinAt(w, zf, at): # -> pin = {} blk -> rev
t = w.tdb t = w.tdb
...@@ -850,7 +850,7 @@ def test_wcfs(): ...@@ -850,7 +850,7 @@ def test_wcfs():
# XXX both from scratch and going e.g. at1 -> at2 -> at3 # XXX both from scratch and going e.g. at1 -> at2 -> at3
# XXX going not only up, but also down at1 <- at2 <- at3 ? # XXX going not only up, but also down at1 <- at2 <- at3 ? -> forbid
# XXX 2 (or more) opened watch for 1 file at the same time # XXX 2 (or more) opened watch for 1 file at the same time
# XXX watch for 2 files via single watch open # XXX watch for 2 files via single watch open
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment