Commit 5d73770d authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 6df31f29
......@@ -218,7 +218,8 @@ type ΔTree struct {
// XXX is a set of PP(leafs) nodes XXX -> PTreeSubSet ? TreePSubSet ? TreePPSet ? PPSubSet ?
// XXX PPNodeSet? TreePPSubSet ?
// XXX PPNodeSet? TreePPSubSet ? PPSet? PPNodeSet? PPOidSet?
// ~~ PPOidSet ~~ <- Y
//
// where PP maps a leaf to {leaf, leaf.parent, leaf.parent.parent, ...} up to
// top root node from where the leaf is reached.
......@@ -228,7 +229,7 @@ type ΔTree struct {
// XXX place
type trackIndex map[zodb.Oid]*nodeTrack
// XXX place XXX PTreeSubSetNode ?
// XXX place XXX PTreeSubSetNode ? PPNode? nodeP? nodePnC ?
// nodeTrack represents tracking information about a node.
type nodeTrack struct {
parent zodb.Oid // parent node | InvalidOid for root
......@@ -239,15 +240,20 @@ type nodeTrack struct {
*/
}
// δtrackIndex represents change to trackIndex.
// δtrackIndex represents change to trackIndex. XXX name
//
// The result B of applying δ to A is:
//
// B = A.Difference(δ.Del).Union(δ.Add)
// XXX place
type δtrackIndex struct {
/*
// set of leaf nodes to remove. After leafs are removed, their parents
// are automatically cleaned down-up. Removals are processed before
// adds (see below).
DelLeaf SetOid
// nodes to add XXX -> add/modify ?
*/
Del trackIndex
Add trackIndex
}
......@@ -326,82 +332,40 @@ func (tidx trackIndex) verify() {
//
// In other words it removes B nodes from A while still maintaining A as P-connected.
func (A trackIndex) DifferenceInplace(B trackIndex) {
//fmt.Printf("\n\nDifferenceInplace:\n")
//fmt.Printf("A: %s\n", A)
//fmt.Printf("B: %s\n", B)
fmt.Printf("\n\nDifferenceInplace:\n")
fmt.Printf(" A: %s\n", A)
fmt.Printf(" B: %s\n", B)
defer fmt.Printf("->D: %s\n", A)
A.verify()
B.verify()
defer A.verify()
panic("TODO")
}
// UnionInplace sets A = PP(A.leafs | B.leafs)
//
// In other words it adds B nodes to A.
func (A trackIndex) UnionInplace(B trackIndex) {
//fmt.Printf("\n\nUnionInplace:\n")
//fmt.Printf("A: %s\n", A)
//fmt.Printf("B: %s\n", B)
A.verify()
B.verify()
defer A.verify()
δnchild := map[zodb.Oid]int{}
// remove B.leafs and thier parents
for oid, t2 := range B {
t, already := A[oid]
if !already {
t = &nodeTrack{parent: t2.parent, nchild: t2.nchild}
A[oid] = t
} else {
if t2.parent != t.parent {
// XXX or verify this at Track time and require
// that update is passed only entries with the
// same .parent? (then it would be ok to panic here)
// XXX -> error (e.g. due to corrupt data in ZODB)
panicf("node %s is reachable from multiple parents: %s %s",
oid, t.parent, t2.parent)
}
t.nchild += t2.nchild
if t.parent != zodb.InvalidOid {
// this node is already present in both trees
// compensate for that in its parent (which must be present)
A[t.parent].nchild--
}
if t2.nchild != 0 {
continue // not a leaf
}
}
}
// ApplyΔ applies δ to trackIdx. XXX
func (tidx trackIndex) ApplyΔ(δ *δtrackIndex) {
//fmt.Printf("\n\nApplyΔ\n")
//fmt.Printf("\ttidx: %v\n", tidx)
//fmt.Printf("\tDelLeaf: %v\n", δ.DelLeaf)
//fmt.Printf("\tAdd: %v\n", δ.Add)
//defer fmt.Printf("\n\t-> tidx: %v\n", tidx)
tidx.verify()
δnchild := map[zodb.Oid]int{}
// remove leafs and thier parents
for leaf := range δ.DelLeaf {
t, present := tidx[leaf]
t, present := A[oid]
if !present {
continue // already not there
}
delete(tidx, leaf)
// XXX assert t.parent == t2.parent ?
delete(A, oid)
if t.parent != zodb.InvalidOid {
δnchild[t.parent] -= 1
}
}
/* XXX kill
// process adds
for oid, δt := range δ.Add {
t, already := tidx[oid]
t, already := A[oid]
if already {
if t.parent != zodb.InvalidOid {
δnchild[t.parent] -= 1
......@@ -409,18 +373,19 @@ func (tidx trackIndex) ApplyΔ(δ *δtrackIndex) {
}
} else {
t = &nodeTrack{parent: δt.parent, nchild: 0}
tidx[oid] = t
A[oid] = t
}
if t.parent != zodb.InvalidOid {
δnchild[t.parent] += 1 // remeber to nchild++ in parent
}
}
*/
// perform scheduled δnchild adjustment
gcq := []zodb.Oid{}
for oid, δnc := range δnchild {
t := tidx[oid] // XXX t can be nil -> XXX no must be there as tidx is connected
t := A[oid] // XXX t can be nil -> XXX no must be there as A is connected
t.nchild += δnc
if t.nchild == 0 && /* not root node */t.parent != zodb.InvalidOid {
gcq = append(gcq, oid)
......@@ -429,10 +394,64 @@ func (tidx trackIndex) ApplyΔ(δ *δtrackIndex) {
// GC parents that became to have .nchild == 0
for _, oid := range gcq {
tidx.gc1(oid)
A.gc1(oid)
}
}
// UnionInplace sets A = PP(A.leafs | B.leafs)
//
// In other words it adds B nodes to A.
func (A trackIndex) UnionInplace(B trackIndex) {
fmt.Printf("\n\nUnionInplace:\n")
fmt.Printf(" A: %s\n", A)
fmt.Printf(" B: %s\n", B)
defer fmt.Printf("->U: %s\n", A)
A.verify()
B.verify()
defer A.verify()
for oid, t2 := range B {
t, already := A[oid]
if !already {
t = &nodeTrack{parent: t2.parent, nchild: t2.nchild}
A[oid] = t
} else {
if t2.parent != t.parent {
// XXX or verify this at Track time and require
// that update is passed only entries with the
// same .parent? (then it would be ok to panic here)
// XXX -> error (e.g. due to corrupt data in ZODB)
panicf("node %s is reachable from multiple parents: %s %s",
oid, t.parent, t2.parent)
}
t.nchild += t2.nchild
if t.parent != zodb.InvalidOid {
// this node is already present in both trees
// compensate for that in its parent (which must be present)
A[t.parent].nchild--
}
}
}
}
// ApplyΔ applies δ to trackIdx. XXX
func (tidx trackIndex) ApplyΔ(δ *δtrackIndex) {
fmt.Printf("\n\nApplyΔ\n")
fmt.Printf(" A: %s\n", tidx)
fmt.Printf(" -: %s\n", δ.Del)
fmt.Printf(" +: %s\n", δ.Add)
defer fmt.Printf("\n->B: %s\n", tidx)
tidx.verify()
δ.Del.verify()
δ.Add.verify()
defer tidx.verify()
tidx.DifferenceInplace(δ.Del)
tidx.UnionInplace(δ.Add)
}
// treeSetKey represents ordered set of keys.
......@@ -601,6 +620,28 @@ func (δBtail *ΔBtail) holeIdxFor(root zodb.Oid) treeSetKey {
return holeIdx
}
// Path returns path leading to node speficied by oid.
//
// The node must be in the set.
// XXX place
func (tidx trackIndex) Path(oid zodb.Oid) (path []zodb.Oid) {
for {
t, ok := tidx[oid]
if !ok {
panicf("node %s is not in the set <- %v", oid, path)
}
path = append([]zodb.Oid{oid}, path...)
oid = t.parent
if oid == zodb.InvalidOid {
break
}
}
return path
}
// XXX place
// XXX doc
func (tidx trackIndex) AddNodePath(path []Node) { // XXX Tree|Bucket; path[0] = root
......@@ -615,6 +656,9 @@ func (tidx trackIndex) AddNodePath(path []Node) { // XXX Tree|Bucket; path[0] =
}
func (tidx trackIndex) AddPath(path []zodb.Oid) {
tidx.verify()
defer tidx.verify()
l := len(path)
if l == 0 {
panic("empty path")
......@@ -1140,6 +1184,7 @@ func treediff(ctx context.Context, root zodb.Oid, δtops SetOid, δZTC SetOid, t
}
// adjust trackIdx by merge(δtrackTops)
/*
δtrack := &δtrackIndex{DelLeaf: SetOid{}, Add: trackIndex{}}
for _, δ := range δtrackv {
δtrack.DelLeaf.Update(δ.DelLeaf)
......@@ -1147,6 +1192,12 @@ func treediff(ctx context.Context, root zodb.Oid, δtops SetOid, δZTC SetOid, t
δtrack.Add[oid] = t // XXX verify changes from 2 δtrackTops are consistent
}
}
*/
δtrack := &δtrackIndex{Del: trackIndex{}, Add: trackIndex{}}
for _, δ := range δtrackv {
δtrack.Del.UnionInplace(δ.Del)
δtrack.Add.UnionInplace(δ.Add)
}
trackIdx.ApplyΔ(δtrack)
return δT, nil
......@@ -1221,7 +1272,8 @@ func diffT(ctx context.Context, A, B *Tree, δZTC SetOid, trackIdx trackIndex, h
if B == nil { panic("B is nil") }
δ = map[Key]ΔValue{}
δtrack = &δtrackIndex{DelLeaf: SetOid{}, Add: trackIndex{}}
// δtrack = &δtrackIndex{DelLeaf: SetOid{}, Add: trackIndex{}}
δtrack = &δtrackIndex{Del: trackIndex{}, Add: trackIndex{}}
defer tracef(" -> δ: %v\n", δ)
// path prefix to A and B
......@@ -1261,7 +1313,9 @@ func diffT(ctx context.Context, A, B *Tree, δZTC SetOid, trackIdx trackIndex, h
// XXX
// XXX requires A.oid == B.oid
// XXX -> trackIndex
BtrackIdx := map[zodb.Oid]nodeTrack{B.POid(): nodeTrack{parent: trackIdx[B.POid()].parent}}
// BtrackIdx := map[zodb.Oid]nodeTrack{B.POid(): nodeTrack{parent: trackIdx[B.POid()].parent}}
BtrackIdx := trackIndex{}
BtrackIdx.AddPath(trackIdx.Path(B.POid()))
// phase 1: expand A top->down driven by δZTC.
// by default a node contributes to δ-
......@@ -1284,7 +1338,8 @@ func diffT(ctx context.Context, A, B *Tree, δZTC SetOid, trackIdx trackIndex, h
// a is bucket -> δ-
δA, err := diffB(ctx, a, nil); /*X*/if err != nil { return nil,nil, err }
err = δMerge(δ, δA); /*X*/if err != nil { return nil,nil, err }
δtrack.DelLeaf.Add(a.POid())
// δtrack.DelLeaf.Add(a.POid())
δtrack.Del.AddPath(ra.Path())
// Bkqueue <- δA
for k := range δA {
......@@ -1341,7 +1396,8 @@ func diffT(ctx context.Context, A, B *Tree, δZTC SetOid, trackIdx trackIndex, h
bchildren := Bv.Expand(blo)
for _, bc := range bchildren {
bcOid := bc.node.POid()
BtrackIdx[bcOid] = nodeTrack{parent: blo.node.POid()}
// BtrackIdx[bcOid] = nodeTrack{parent: blo.node.POid()}
BtrackIdx.AddPath(bc.Path())
if acOid == bcOid {
found = true
}
......@@ -1356,6 +1412,14 @@ func diffT(ctx context.Context, A, B *Tree, δZTC SetOid, trackIdx trackIndex, h
// XXX Bkqueue <- holes(ac.range \ bc.range) XXX test for this
// adjust trackIdx since path to the node could have changed
apath := trackIdx.Path(acOid)
bpath := BtrackIdx.Path(acOid)
if !reflect.DeepEqual(apath, bpath) {
δtrack.Del.AddPath(apath)
δtrack.Add.AddPath(bpath)
}
/* XXX kill
oid := acOid
for oid != zodb.InvalidOid {
told := trackIdx[oid]
......@@ -1364,11 +1428,12 @@ func diffT(ctx context.Context, A, B *Tree, δZTC SetOid, trackIdx trackIndex, h
break
}
if told == nil || (told.parent != tnew.parent) {
δtrack.Add[oid] = &tnew // XXX adjust nchildren
δtrack.Add.AddPath(BtrackIdx.Path(oid))
}
oid = tnew.parent
}
*/
continue
}
......@@ -1453,7 +1518,8 @@ func diffT(ctx context.Context, A, B *Tree, δZTC SetOid, trackIdx trackIndex, h
// δ <- δA
err = δMerge(δ, δA); /*X*/if err != nil { return nil,nil, err }
δtrack.DelLeaf.Add(a.node.POid())
// δtrack.DelLeaf.Add(a.node.POid())
δtrack.Del.AddPath(a.Path())
// Bkqueue <- δA
for k_ := range δA {
......
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