Commit d245e5ef authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 56ee365c
...@@ -554,8 +554,12 @@ type BigFile struct { ...@@ -554,8 +554,12 @@ type BigFile struct {
loadMu sync.Mutex loadMu sync.Mutex
loading map[int64]*blkLoadState // #blk -> {... blkdata} loading map[int64]*blkLoadState // #blk -> {... blkdata}
// watches attached to this file // watches attached to this file.
// XXX already in "established" state (i.e. initial watch request was answered with "ok") //
// both watches in already "established" state (i.e. initial watch
// request was completed and answered with "ok"), and watches in
// progress of being established. XXX text
//
// XXX locking -> watchMu? // XXX locking -> watchMu?
watches map[*Watch]struct{} watches map[*Watch]struct{}
} }
...@@ -608,7 +612,6 @@ type Watch struct { ...@@ -608,7 +612,6 @@ type Watch struct {
// XXX locking // XXX locking
at zodb.Tid // requested to be watched @at at zodb.Tid // requested to be watched @at
// pinned SetI64 // blocks that are already pinned to be ≤ at
// {} blk -> rev // {} blk -> rev
pinned map[int64]zodb.Tid // blocks that are already pinned to be ≤ at pinned map[int64]zodb.Tid // blocks that are already pinned to be ≤ at
...@@ -1362,7 +1365,7 @@ func (w *Watch) pin(ctx context.Context, blk int64, rev zodb.Tid) (err error) { ...@@ -1362,7 +1365,7 @@ func (w *Watch) pin(ctx context.Context, blk int64, rev zodb.Tid) (err error) {
return nil return nil
} }
// setupWatch sets up a Watch when client sends `watch <file> @<at>` request. // setupWatch sets up or updates a Watch when client sends `watch <file> @<at>` request.
// //
// XXX sends "pin" notifications; final "ok" must be sent by caller. // XXX sends "pin" notifications; final "ok" must be sent by caller.
// //
...@@ -1391,13 +1394,12 @@ func (wlink *WatchLink) setupWatch(ctx context.Context, foid zodb.Oid, at zodb.T ...@@ -1391,13 +1394,12 @@ func (wlink *WatchLink) setupWatch(ctx context.Context, foid zodb.Oid, at zodb.T
link: wlink, link: wlink,
file: f, file: f,
at: at, at: at,
//pinned: make(SetI64),
pinned: make(map[int64]zodb.Tid), pinned: make(map[int64]zodb.Tid),
} }
} }
// XXX check at >= w.at // XXX check at >= w.at -> reject?
if !(at >= w.at) { if !(at >= w.at) {
panic("TODO") panic("TODO")
} }
...@@ -1413,10 +1415,16 @@ func (wlink *WatchLink) setupWatch(ctx context.Context, foid zodb.Oid, at zodb.T ...@@ -1413,10 +1415,16 @@ func (wlink *WatchLink) setupWatch(ctx context.Context, foid zodb.Oid, at zodb.T
headAt, headAt.Time().Sub(at.Time().Time)) headAt, headAt.Time().Sub(at.Time().Time))
} }
// TODO register w to f here early, so that READs going in parallel to f := w.file
// us preparing and processing initial pins, also send pins for read
// register w to f here early, so that READs going in parallel to us
// preparing and processing initial pins, also send pins for read
// 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 . XXX test
// XXX locking
// XXX register only if watch was created anew, not updated.
f.watches[w] = struct{}{}
// pin all tracked file blocks that were changed in (at, head] range. // pin all tracked file blocks that were changed in (at, head] range.
...@@ -1424,7 +1432,6 @@ func (wlink *WatchLink) setupWatch(ctx context.Context, foid zodb.Oid, at zodb.T ...@@ -1424,7 +1432,6 @@ func (wlink *WatchLink) setupWatch(ctx context.Context, foid zodb.Oid, at zodb.T
toPin := map[int64]zodb.Tid{} // blk -> @rev toPin := map[int64]zodb.Tid{} // blk -> @rev
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 {
_, already := toPin[blk] _, already := toPin[blk]
...@@ -1615,14 +1622,12 @@ func (wlink *WatchLink) handleWatch(ctx context.Context, stream uint64, msg stri ...@@ -1615,14 +1622,12 @@ func (wlink *WatchLink) handleWatch(ctx context.Context, stream uint64, msg stri
err = wlink._handleWatch(ctx, msg) err = wlink._handleWatch(ctx, msg)
reply := "ok" reply := "ok"
if err != nil { if err != nil {
// logical error is reported back to client, but watch link remains live
reply = fmt.Sprintf("error %s", err) reply = fmt.Sprintf("error %s", err)
err = nil err = nil
} }
err2 := wlink.send(ctx, stream, reply) err = wlink.send(ctx, stream, reply)
if err == nil {
err = err2
}
return err return err
} }
...@@ -1889,10 +1894,7 @@ func (head *Head) bigopen(ctx context.Context, oid zodb.Oid) (_ *BigFile, err er ...@@ -1889,10 +1894,7 @@ func (head *Head) bigopen(ctx context.Context, oid zodb.Oid) (_ *BigFile, err er
loading: make(map[int64]*blkLoadState), loading: make(map[int64]*blkLoadState),
} }
// only head/ needs f.δtail // only head/ needs δFtail, f.δtail and watches.
// only head/ needs δFtail & f.δtail.
if head.rev == 0 { if head.rev == 0 {
head.bfdir.δFmu.Lock() // XXX locking ok? head.bfdir.δFmu.Lock() // XXX locking ok?
head.bfdir.δFtail.Track(f, -1, sizePath, nil) head.bfdir.δFtail.Track(f, -1, sizePath, nil)
...@@ -1900,6 +1902,8 @@ func (head *Head) bigopen(ctx context.Context, oid zodb.Oid) (_ *BigFile, err er ...@@ -1900,6 +1902,8 @@ func (head *Head) bigopen(ctx context.Context, oid zodb.Oid) (_ *BigFile, err er
// FIXME: scan zfile.blktab - so that we can detect all btree changes // FIXME: scan zfile.blktab - so that we can detect all btree changes
// see "XXX building δFtail lazily ..." in notes.txt // see "XXX building δFtail lazily ..." in notes.txt
f.watches = make(map[*Watch]struct{})
} }
return f, nil return f, nil
......
...@@ -750,7 +750,7 @@ def watch(twlink, zf, at): # XXX -> ? ...@@ -750,7 +750,7 @@ def watch(twlink, zf, at): # XXX -> ?
# blk ∈ pin_prev, blk ∉ pin -> unpin to head # blk ∈ pin_prev, blk ∉ pin -> unpin to head
elif blk in pin_prev and blk not in pin: elif blk in pin_prev and blk not in pin:
pin[blk] = None # XXX = head pin[blk] = None # @head
# blk ∈ pin_prev, blk ∈ pin -> if rev different: use pin # blk ∈ pin_prev, blk ∈ pin -> if rev different: use pin
elif blk in pin_prev and blk in pin: elif blk in pin_prev and blk in pin:
...@@ -986,6 +986,8 @@ def test_wcfs(): ...@@ -986,6 +986,8 @@ def test_wcfs():
assert ev == ['read pre', 'pin rx', 'pin ack', 'read post'] assert ev == ['read pre', 'pin rx', 'pin ack', 'read post']
assert f.cached()[2] == 1 assert f.cached()[2] == 1
wl.close()
# XXX commit after current file size -> watch # XXX commit after current file size -> watch
...@@ -1031,6 +1033,8 @@ def test_wcfs(): ...@@ -1031,6 +1033,8 @@ def test_wcfs():
# XXX read file[blk]=hole; then file[blk]=zblk - must be invalidated and # XXX read file[blk]=hole; then file[blk]=zblk - must be invalidated and
# setupWatch must send pins. # setupWatch must send pins.
# XXX no reply to pin - killed
# ---- misc --- # ---- misc ---
......
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