Commit e1f69447 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 31904634
...@@ -105,24 +105,95 @@ func (S PPTreeSubSet) verify() { ...@@ -105,24 +105,95 @@ func (S PPTreeSubSet) verify() {
} }
} }
// DifferenceInplace sets A = PP(A.leafs \ B.leafs) // Path returns path leading to node specified by oid.
// //
// In other words it removes B nodes from A while still maintaining A as P-connected. // The node must be in the set.
func (A PPTreeSubSet) DifferenceInplace(B PPTreeSubSet) { func (S PPTreeSubSet) Path(oid zodb.Oid) (path []zodb.Oid) {
if debugPPSet { for {
fmt.Printf("\n\nDifferenceInplace:\n") t, ok := S[oid]
fmt.Printf(" A: %s\n", A) if !ok {
fmt.Printf(" B: %s\n", B) panicf("node %s is not in the set <- %v", oid, path)
defer fmt.Printf("->D: %s\n", A) }
path = append([]zodb.Oid{oid}, path...)
oid = t.parent
if oid == zodb.InvalidOid {
break
}
} }
A.verify() return path
B.verify() }
defer A.verify()
A.xDifferenceInplace(B) // XXX doc
func (S PPTreeSubSet) AddNodePath(path []Node) { // XXX Tree|Bucket; path[0] = root
// XXX assert Tree Tree ... Tree Bucket
// root := path[0].(*Tree).POid()
oidv := []zodb.Oid{}
for _, node := range path {
oidv = append(oidv, node.POid())
}
S.AddPath(oidv)
} }
// XXX doc
func (S PPTreeSubSet) AddPath(path []zodb.Oid) {
S.verify()
defer S.verify()
l := len(path)
if l == 0 {
panic("empty path")
}
// don't explicitly keep track of embedded buckets - they all have
// InvalidOid, and thus, if kept in S, e.g. T/B1:a and another
// T/B2:b would lead to InvalidOid having multiple parents.
if l >= 2 && path[l-1] == zodb.InvalidOid {
path = path[:l-1]
}
parent := zodb.InvalidOid
var ptrack *nodeInTree = nil
var track *nodeInTree // XXX kill here
var oldTrack bool
for _, oid := range path {
if oid == zodb.InvalidOid {
panicf("path has node with invalid oid: %v", path)
}
track, oldTrack = S[oid]
if !oldTrack {
track = &nodeInTree{parent: parent, nchild: 0} // XXX
/*
if i == l-1 { // leaf
track.holes = SetKey{}
}
*/
S[oid] = track
// XXX .trackNew += oid
}
if track.parent != parent {
// XXX -> error (e.g. due to corrupt data in ZODB)
panicf("node %s is reachable from multiple parents: %s %s",
oid, track.parent, parent)
}
if ptrack != nil && !oldTrack {
ptrack.nchild++
}
parent = oid
ptrack = track
}
}
// ---- Union/Difference ----
// UnionInplace sets A = PP(A.leafs | B.leafs) // UnionInplace sets A = PP(A.leafs | B.leafs)
// //
// In other words it adds B nodes to A. // In other words it adds B nodes to A.
...@@ -141,44 +212,22 @@ func (A PPTreeSubSet) UnionInplace(B PPTreeSubSet) { ...@@ -141,44 +212,22 @@ func (A PPTreeSubSet) UnionInplace(B PPTreeSubSet) {
A.xUnionInplace(B) A.xUnionInplace(B)
} }
// DifferenceInplace sets A = PP(A.leafs \ B.leafs)
func (A PPTreeSubSet) xDifferenceInplace(B PPTreeSubSet) { //
// In other words it removes B nodes from A while still maintaining A as P-connected.
func (A PPTreeSubSet) DifferenceInplace(B PPTreeSubSet) {
if debugPPSet { if debugPPSet {
fmt.Printf("\n\n xDifferenceInplace:\n") fmt.Printf("\n\nDifferenceInplace:\n")
fmt.Printf(" a: %s\n", A) fmt.Printf(" A: %s\n", A)
fmt.Printf(" b: %s\n", B) fmt.Printf(" B: %s\n", B)
defer fmt.Printf(" ->d: %s\n", A) defer fmt.Printf("->D: %s\n", A)
} }
δnchild := map[zodb.Oid]int{} A.verify()
B.verify()
// remove B.leafs and their parents defer A.verify()
for oid, t2 := range B {
if t2.nchild != 0 {
continue // not a leaf
}
t, present := A[oid]
if !present {
continue // already not there
}
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)
}
delete(A, oid)
if t.parent != zodb.InvalidOid {
δnchild[t.parent] -= 1
}
}
A.fixup(δnchild) A.xDifferenceInplace(B)
} }
func (A PPTreeSubSet) xUnionInplace(B PPTreeSubSet) { func (A PPTreeSubSet) xUnionInplace(B PPTreeSubSet) {
...@@ -215,6 +264,45 @@ func (A PPTreeSubSet) xUnionInplace(B PPTreeSubSet) { ...@@ -215,6 +264,45 @@ func (A PPTreeSubSet) xUnionInplace(B PPTreeSubSet) {
A.fixup(δnchild) A.fixup(δnchild)
} }
func (A PPTreeSubSet) xDifferenceInplace(B PPTreeSubSet) {
if debugPPSet {
fmt.Printf("\n\n xDifferenceInplace:\n")
fmt.Printf(" a: %s\n", A)
fmt.Printf(" b: %s\n", B)
defer fmt.Printf(" ->d: %s\n", A)
}
δnchild := map[zodb.Oid]int{}
// remove B.leafs and their parents
for oid, t2 := range B {
if t2.nchild != 0 {
continue // not a leaf
}
t, present := A[oid]
if !present {
continue // already not there
}
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)
}
delete(A, oid)
if t.parent != zodb.InvalidOid {
δnchild[t.parent] -= 1
}
}
A.fixup(δnchild)
}
// fixup performs scheduled δnchild adjustment. // fixup performs scheduled δnchild adjustment.
func (A PPTreeSubSet) fixup(δnchild map[zodb.Oid]int) { func (A PPTreeSubSet) fixup(δnchild map[zodb.Oid]int) {
A.xfixup(+1, δnchild) A.xfixup(+1, δnchild)
...@@ -259,92 +347,6 @@ func (S PPTreeSubSet) gc1(oid zodb.Oid) { ...@@ -259,92 +347,6 @@ func (S PPTreeSubSet) gc1(oid zodb.Oid) {
} }
// Path returns path leading to node specified by oid.
//
// The node must be in the set.
func (S PPTreeSubSet) Path(oid zodb.Oid) (path []zodb.Oid) {
for {
t, ok := S[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 doc
func (S PPTreeSubSet) AddNodePath(path []Node) { // XXX Tree|Bucket; path[0] = root
// XXX assert Tree Tree ... Tree Bucket
// root := path[0].(*Tree).POid()
oidv := []zodb.Oid{}
for _, node := range path {
oidv = append(oidv, node.POid())
}
S.AddPath(oidv)
}
// XXX doc
func (S PPTreeSubSet) AddPath(path []zodb.Oid) {
S.verify()
defer S.verify()
l := len(path)
if l == 0 {
panic("empty path")
}
// don't explicitly keep track of embedded buckets - they all have
// InvalidOid, and thus, if kept in S, e.g. T/B1:a and another
// T/B2:b would lead to InvalidOid having multiple parents.
if l >= 2 && path[l-1] == zodb.InvalidOid {
path = path[:l-1]
}
parent := zodb.InvalidOid
var ptrack *nodeInTree = nil
var track *nodeInTree // XXX kill here
var oldTrack bool
for _, oid := range path {
if oid == zodb.InvalidOid {
panicf("path has node with invalid oid: %v", path)
}
track, oldTrack = S[oid]
if !oldTrack {
track = &nodeInTree{parent: parent, nchild: 0} // XXX
/*
if i == l-1 { // leaf
track.holes = SetKey{}
}
*/
S[oid] = track
// XXX .trackNew += oid
}
if track.parent != parent {
// XXX -> error (e.g. due to corrupt data in ZODB)
panicf("node %s is reachable from multiple parents: %s %s",
oid, track.parent, parent)
}
if ptrack != nil && !oldTrack {
ptrack.nchild++
}
parent = oid
ptrack = track
}
}
// Clone returns copy of the set. // Clone returns copy of the set.
// XXX place // XXX place
func (orig PPTreeSubSet) Clone() PPTreeSubSet { func (orig PPTreeSubSet) Clone() PPTreeSubSet {
......
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