Commit 07966f0d authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent d5a07d5f
......@@ -507,6 +507,7 @@ type nodeInRange struct {
// rangeCover represents set of nodes covering a range.
// nodes come with key↑ and not intersection [lo,hi)
// XXX -> nodeSet? nodeSetInRange?
type rangeCover []*nodeInRange // key↑
// Get returns node covering key k.
......@@ -784,6 +785,160 @@ func diffT(ctx context.Context, a, b *Tree, δZTC SetOid, trackIdx map[zodb.Oid]
}
return δ, nil
}
func __diffT(ctx context.Context, a, b *Tree, δZTC SetOid, trackIdx map[zodb.Oid]nodeTrack) (δ map[Key]ΔValue, err error) {
fmt.Printf(" T %s %s\n", xidOf(a), xidOf(b))
defer xerr.Contextf(&err, "diffT %s %s", xidOf(a), xidOf(b))
var av []TreeEntry
var bv []TreeEntry
if a != nil {
err = a.PActivate(ctx); if err != nil { return nil, err }
defer a.PDeactivate()
av = a.Entryv() // key↑
}
if b != nil {
err = b.PActivate(ctx); if err != nil { return nil, err }
defer b.PDeactivate()
bv = b.Entryv() // key↑
}
fmt.Printf(" av: %s\n", vtree(av))
fmt.Printf(" bv: %v\n", vtree(bv))
δ = map[Key]ΔValue{}
defer fmt.Printf(" -> δt: %v\n", δ)
// [i].Key ≤ [i].Child.*.Key < [i+1].Key i ∈ [0, len([]))
//
// [0].Key = -∞ ; always returned so
// [len(ev)].Key = +∞ ; should be assumed so
// a -> {aChildren} : ∈ δZTC
aChildren := map[zodb.Oid]Node{}
for _, __ := range av {
child := __.Child()
coid := child.POid()
if δZTC.Has(coid) ||
(len(av) == 1 && coid == zodb.InvalidOid) /* embedded bucket */ {
aChildren[coid] = child
}
}
fmt.Printf(" aChildren: %v\n", aChildren)
// -> "might be changed" subset of tracked keys
δtqkeys := SetKey{}
for achild := range aChildren {
track, ok := trackIdx[achild]
if !ok {
panicf("node %s ∈ δZTC, but its track is ø", achild)
}
δtqkeys.Update(track.trackedKeys)
}
if a != nil && len(av) == 0 { // ø tree - fetch tracked keys from it directly
δtqkeys.Update(trackIdx[a.POid()].trackedKeys)
}
fmt.Printf(" δtqkeys: %s\n", δtqkeys)
// b -> {bChildren} : coverage ∩ "might be changed" tracked keys
bChildren := map[zodb.Oid]Node{}
for i := range bv {
lo := bv[i].Key() // [lo, hi_] _not_ hi) not to overflow at ∞
hi_ := KeyMax
if i+1 < len(bv) {
hi_ = bv[i+1].Key() - 1
}
child := bv[i].Child()
// XXX dumb
for k := range δtqkeys {
if lo <= k && k <= hi_ {
bChildren[child.POid()] = child // InvalidOid = embedded bucket
break
}
}
}
fmt.Printf(" bChildren: %v\n", bChildren)
// allChildren = aChildren ∪ bChildren
allChildren := SetOid{}
for c := range aChildren { allChildren.Add(c) }
for c := range bChildren { allChildren.Add(c) }
// go through all children that potentially can add to δ and process add/del/modify
for child := range allChildren { // XXX -> sorted? FIXME wrong to traverse by oid - need to ...?
ca := aChildren[child]
cb := bChildren[child]
δc, err := diffX(ctx, ca, cb, δZTC, trackIdx)
if err != nil {
return nil, err
}
// merge δ <- δc
for k, δv1 := range δc {
δv2, already := δ[k]
if !already {
δ[k] = δv1
continue
}
// both δ and δc has [k] - it can be that key
// entry migrated from one bucket into another.
if !( (δv2.New == VDEL && δv1.Old == VDEL) ||
(δv2.Old == VDEL && δv1.New == VDEL) ) {
return nil, fmt.Errorf("BUG or btree corrupt: [%v] has " +
"duplicate entries: %v, %v", k, δv1, δv2)
}
δv := ΔValue{}
if δv1.New == VDEL {
δv.Old = δv1.Old
δv.New = δv2.New
} else {
δv.Old = δv2.Old
δv.New = δv1.New
}
fmt.Printf(" [%v] merge %s %s -> %s\n", k, δv1, δv2, δv)
if δv.Old != δv.New {
δ[k] = δv
} else {
delete(δ, k)
}
}
// update δc -> tracked keys
// ca = nil -> add cb to tracked
// cb = nil -> remove ca from tracked
// (their siblings must be already processed by diffX call)
if ca == nil {
trackIdx[child] = nodeTrack{parent: b.POid(), trackedKeys: SetKey{}}
}
if cb == nil {
delete(trackIdx, child) // XXX remove keys from parent?
} else {
trackedKeys := trackIdx[child].trackedKeys
for k, δv := range δc {
switch {
case δv.Old == VDEL:
trackedKeys.Add(k)
case δv.New == VDEL:
trackedKeys.Add(k)
// k v1->v2 no change in key
}
}
}
}
/*
allChildren := SetOid{}
for _, __ := range av {
......
......@@ -283,7 +283,7 @@ type RBucketSet []*RBucket // k↑
// Get returns RBucket which covers key k.
func (rbs RBucketSet) Get(k Key) *RBucket {
i := sort.Search(len(rbs), func(i int) bool {
return rbs[i].hi > k
return k < rbs[i].hi
})
if i == len(rbs) {
panicf("BUG: key %v not covered; coverage: %s", k, rbs.coverage())
......
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