Commit d741c8c7 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent e09b503e
...@@ -504,15 +504,54 @@ func (δTtail *ΔTtail) rebuild1(atPrev zodb.Tid, δZ zodb.ΔRevEntry, trackNew ...@@ -504,15 +504,54 @@ func (δTtail *ΔTtail) rebuild1(atPrev zodb.Tid, δZ zodb.ΔRevEntry, trackNew
// //
// TODO optionally accept zconnOld/zconnNew from client // TODO optionally accept zconnOld/zconnNew from client
func (δBtail *ΔBtail) Update(δZ *zodb.EventCommit) (_ ΔB, err error) { func (δBtail *ΔBtail) Update(δZ *zodb.EventCommit) (_ ΔB, err error) {
δB, _, err := δBtail._Update(δZ) δTKeyCov1, err := δBtail._Update1(δZ)
δB := ΔB{Rev: δZ.Tid, ΔByRoot: make(map[zodb.Oid]map[Key]ΔValue)}
for root, δtkeycov1 := range δTKeyCov1.ByRoot {
δTtail := δBtail.vδTbyRoot[root] // must succeed
// δtkeycov1 != ø -> rebuild δTtail
if !δtkeycov1.Empty() && δBtail.δZtail.Len() > 1 {
//δTtail.trackNew = ... // ~δtkeycov1
δTtail.trackNew = nil // XXX stub
// XXX vvv we can skip computing diff for HEAD~..HEAD (we just
// computed it)
δtrackSet, err := δTtail.rebuild(root, δBtail.δZtail, δBtail.db)
if err != nil {
return ΔB{}, err
}
δBtail.trackSet.UnionInplace(δtrackSet)
// XXX Update δTKeyCov? XXX or it is needed only to be returned
// from treediff?
}
// build δB. Even if δT=ø after _Update1, but δtkeycov1 != ø, above
// rebuild could result in head δT becoming != ø. Detect that δTtail head
// is anew by comparing to δZ.Rev.
l := len(δTtail.vδT)
if l > 0 {
δT := δTtail.vδT[l-1] // δT head
if δT.Rev == δZ.Tid {
δB.ΔByRoot[root] = δT.ΔKV
}
}
// XXX rebuild KVAtTail
// XXX rebuild lastRevOf
}
return δB, err return δB, err
} }
// _Update serves Update and also returns δtkeycov from treediff for testing. // _Update1 serves Update and performs direct update of δTtail head elements from δZ.
type _ΔTrackKeyCov struct { // On key coverage growth rebuilding tail of the history is done by Update itself.
ByRoot map[zodb.Oid]*RangedKeySet // {} root -> δtrackedKeys (always grow) XXX δtkeycovByRoot? //
// _Update1 is also used in tests to verify δtkeycov return from treediff.
type _ΔTrackKeyCov1 struct {
ByRoot map[zodb.Oid]*RangedKeySet // {} root -> δtrackedKeys after first treediff (always grow)
} }
func (δBtail *ΔBtail) _Update(δZ *zodb.EventCommit) (_ ΔB, δTKeyCov _ΔTrackKeyCov, err error) { func (δBtail *ΔBtail) _Update1(δZ *zodb.EventCommit) (δTKeyCov1 _ΔTrackKeyCov1, err error) {
headOld := δBtail.Head() headOld := δBtail.Head()
defer xerr.Contextf(&err, "ΔBtail update %s -> %s", headOld, δZ.Tid) defer xerr.Contextf(&err, "ΔBtail update %s -> %s", headOld, δZ.Tid)
...@@ -523,7 +562,7 @@ func (δBtail *ΔBtail) _Update(δZ *zodb.EventCommit) (_ ΔB, δTKeyCov _ΔTrac ...@@ -523,7 +562,7 @@ func (δBtail *ΔBtail) _Update(δZ *zodb.EventCommit) (_ ΔB, δTKeyCov _ΔTrac
tracefΔBtail("[%s].trackNew: %v\n", root, δTtail.trackNew) tracefΔBtail("[%s].trackNew: %v\n", root, δTtail.trackNew)
} }
δTKeyCov = _ΔTrackKeyCov{ByRoot: make(map[zodb.Oid]*RangedKeySet)} δTKeyCov1 = _ΔTrackKeyCov1{ByRoot: make(map[zodb.Oid]*RangedKeySet)}
if XXX_killWhenRebuildWorks { if XXX_killWhenRebuildWorks {
// XXX hack - until vvv is reenabled // XXX hack - until vvv is reenabled
...@@ -538,7 +577,7 @@ if XXX_killWhenRebuildWorks { ...@@ -538,7 +577,7 @@ if XXX_killWhenRebuildWorks {
// update .trackSet and vδB from .trackNew // update .trackSet and vδB from .trackNew
err = δBtail.rebuildAll() err = δBtail.rebuildAll()
if err != nil { if err != nil {
return ΔB{}, δTKeyCov, err return δTKeyCov1, err
} }
} }
...@@ -548,11 +587,9 @@ if XXX_killWhenRebuildWorks { ...@@ -548,11 +587,9 @@ if XXX_killWhenRebuildWorks {
δZTC, δtopsByRoot := δZConnectTracked(δZ.Changev, δBtail.trackSet) δZTC, δtopsByRoot := δZConnectTracked(δZ.Changev, δBtail.trackSet)
δB := ΔB{Rev: δZ.Tid, ΔByRoot: make(map[zodb.Oid]map[Key]ΔValue)}
// skip opening DB connections if there is no change to any tree node // skip opening DB connections if there is no change to any tree node
if len(δtopsByRoot) == 0 { if len(δtopsByRoot) == 0 {
return δB, δTKeyCov, nil return δTKeyCov1, nil
} }
// open ZODB connections corresponding to "old" and "new" states // open ZODB connections corresponding to "old" and "new" states
...@@ -561,54 +598,31 @@ if XXX_killWhenRebuildWorks { ...@@ -561,54 +598,31 @@ if XXX_killWhenRebuildWorks {
defer txn.Abort() defer txn.Abort()
zconnOld, err := δBtail.db.Open(ctx, &zodb.ConnOptions{At: headOld}) zconnOld, err := δBtail.db.Open(ctx, &zodb.ConnOptions{At: headOld})
if err != nil { if err != nil {
return ΔB{}, δTKeyCov, err return δTKeyCov1, err
} }
zconnNew, err := δBtail.db.Open(ctx, &zodb.ConnOptions{At: δZ.Tid}) zconnNew, err := δBtail.db.Open(ctx, &zodb.ConnOptions{At: δZ.Tid})
if err != nil { if err != nil {
return ΔB{}, δTKeyCov, err return δTKeyCov1, err
} }
for root, δtops := range δtopsByRoot { for root, δtops := range δtopsByRoot {
δT, δtrack, δtkeycov, err := treediff(ctx, root, δtops, δZTC, δBtail.trackSet, zconnOld, zconnNew) δT, δtrack, δtkeycov, err := treediff(ctx, root, δtops, δZTC, δBtail.trackSet, zconnOld, zconnNew)
if err != nil { if err != nil {
return ΔB{}, δTKeyCov, err return δTKeyCov1, err
} }
tracefΔBtail("\n-> root<%s> δkv: %v δtrack: %v δtkeycov: %v\n", root, δT, δtrack, δtkeycov) tracefΔBtail("\n-> root<%s> δkv: %v δtrack: %v δtkeycov: %v\n", root, δT, δtrack, δtkeycov)
δTtail := δBtail.vδTbyRoot[root] // must be there δTtail := δBtail.vδTbyRoot[root] // must be there
if len(δT) > 0 { // an object might be resaved without change if len(δT) > 0 { // an object might be resaved without change
δB.ΔByRoot[root] = δT // XXX after rebuild
δTtail.vδT = append(δTtail.vδT, ΔTree{Rev: δZ.Tid, ΔKV: δT}) δTtail.vδT = append(δTtail.vδT, ΔTree{Rev: δZ.Tid, ΔKV: δT})
} }
δBtail.trackSet.ApplyΔ(δtrack) δBtail.trackSet.ApplyΔ(δtrack)
δTKeyCov1.ByRoot[root] = δtkeycov
// δtkeycov != ø -> rebuild δTtail
//
// XXX NOTE `len(δZtail) > 1` check is not only optimization - it is
// important for tests: xverifyΔBTail_Update calls ΔBtail._Update with
// only one revision inside δZtail, and this way also directly exercises
// treediff. Should we drop `len(δZtail) > 1` check here, that test will
// no longer directly exercise treediff behaviour.
if !δtkeycov.Empty() && δBtail.δZtail.Len() > 1 {
δTtail.trackNew = ... // ~δtkeycov
δtrackSet, err := δTtail.rebuild(root, δBtail.δZtail, δBtail.db)
if err != nil {
return ΔB{}, δTKeyCov, err
}
δBtail.trackSet.UnionInplace(δtrackSet)
// XXX Update δTKeyCov? XXX or it is needed only to be returned
// from treediff?
}
δTKeyCov.ByRoot[root] = δtkeycov // XXX after rebuild
// XXX rebuild KVAtTail
// XXX rebuild lastRevOf
} }
return δB, δTKeyCov, nil return δTKeyCov1, nil
} }
......
...@@ -806,7 +806,13 @@ func xverifyΔBTail_Update1(t *testing.T, subj string, db *zodb.DB, treeRoot zod ...@@ -806,7 +806,13 @@ func xverifyΔBTail_Update1(t *testing.T, subj string, db *zodb.DB, treeRoot zod
// δB <- δZ // δB <- δZ
δB, δTKeyCov, err := δbtail._Update(δZ); X(err) δbtail_ := δbtail.Clone()
δB, err := δbtail.Update(δZ); X(err)
δTKeyCov, err := δbtail_._Update1(δZ); X(err)
// XXX assert δB.roots == δTKeyCov roots
// XXX assert δBtail[root].vδT[-1] = δBtail_[root].vδT[-1]
// XXX -> just assert δBtail == δBtail_ ?
if δB.Rev != δZ.Tid { if δB.Rev != δZ.Tid {
badf("δB: rev != δZ.Tid ; rev=%s δZ.Tid=%s", δB.Rev, δZ.Tid) badf("δB: rev != δZ.Tid ; rev=%s δZ.Tid=%s", δB.Rev, δZ.Tid)
return return
......
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