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
//
// TODO optionally accept zconnOld/zconnNew from client
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
}
// _Update serves Update and also returns δtkeycov from treediff for testing.
type _ΔTrackKeyCov struct {
ByRoot map[zodb.Oid]*RangedKeySet // {} root -> δtrackedKeys (always grow) XXX δtkeycovByRoot?
// _Update1 serves Update and performs direct update of δTtail head elements from δZ.
// On key coverage growth rebuilding tail of the history is done by Update itself.
//
// _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()
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
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 {
// XXX hack - until vvv is reenabled
......@@ -538,7 +577,7 @@ if XXX_killWhenRebuildWorks {
// update .trackSet and vδB from .trackNew
err = δBtail.rebuildAll()
if err != nil {
return ΔB{}, δTKeyCov, err
return δTKeyCov1, err
}
}
......@@ -548,11 +587,9 @@ if XXX_killWhenRebuildWorks {
δ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
if len(δtopsByRoot) == 0 {
return δB, δTKeyCov, nil
return δTKeyCov1, nil
}
// open ZODB connections corresponding to "old" and "new" states
......@@ -561,54 +598,31 @@ if XXX_killWhenRebuildWorks {
defer txn.Abort()
zconnOld, err := δBtail.db.Open(ctx, &zodb.ConnOptions{At: headOld})
if err != nil {
return ΔB{}, δTKeyCov, err
return δTKeyCov1, err
}
zconnNew, err := δBtail.db.Open(ctx, &zodb.ConnOptions{At: δZ.Tid})
if err != nil {
return ΔB{}, δTKeyCov, err
return δTKeyCov1, err
}
for root, δtops := range δtopsByRoot {
δT, δtrack, δtkeycov, err := treediff(ctx, root, δtops, δZTC, δBtail.trackSet, zconnOld, zconnNew)
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)
δTtail := δBtail.vδTbyRoot[root] // must be there
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})
}
δBtail.trackSet.ApplyΔ(δtrack)
// δ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
δTKeyCov1.ByRoot[root] = δtkeycov
}
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
// δ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 {
badf("δB: rev != δZ.Tid ; rev=%s δZ.Tid=%s", δB.Rev, δZ.Tid)
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