Commit e1f69447 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 31904634
......@@ -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.
func (A PPTreeSubSet) DifferenceInplace(B PPTreeSubSet) {
if debugPPSet {
fmt.Printf("\n\nDifferenceInplace:\n")
fmt.Printf(" A: %s\n", A)
fmt.Printf(" B: %s\n", B)
defer fmt.Printf("->D: %s\n", A)
// 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)
}
A.verify()
B.verify()
defer A.verify()
path = append([]zodb.Oid{oid}, path...)
oid = t.parent
A.xDifferenceInplace(B)
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
}
}
// ---- Union/Difference ----
// UnionInplace sets A = PP(A.leafs | B.leafs)
//
// In other words it adds B nodes to A.
......@@ -141,28 +212,44 @@ func (A PPTreeSubSet) UnionInplace(B PPTreeSubSet) {
A.xUnionInplace(B)
}
// DifferenceInplace sets A = PP(A.leafs \ B.leafs)
//
// In other words it removes B nodes from A while still maintaining A as P-connected.
func (A PPTreeSubSet) DifferenceInplace(B PPTreeSubSet) {
if debugPPSet {
fmt.Printf("\n\nDifferenceInplace:\n")
fmt.Printf(" A: %s\n", A)
fmt.Printf(" B: %s\n", B)
defer fmt.Printf("->D: %s\n", A)
}
func (A PPTreeSubSet) xDifferenceInplace(B PPTreeSubSet) {
A.verify()
B.verify()
defer A.verify()
A.xDifferenceInplace(B)
}
func (A PPTreeSubSet) xUnionInplace(B PPTreeSubSet) {
if debugPPSet {
fmt.Printf("\n\n xDifferenceInplace:\n")
fmt.Printf("\n\n xUnionInplace:\n")
fmt.Printf(" a: %s\n", A)
fmt.Printf(" b: %s\n", B)
defer fmt.Printf(" ->d: %s\n", A)
defer fmt.Printf(" ->u: %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
t, already := A[oid]
if !already {
t = &nodeInTree{parent: t2.parent, nchild: 0}
A[oid] = t
// remember to nchild++ in parent
if t.parent != zodb.InvalidOid {
δnchild[t.parent] += 1
}
} else {
if t2.parent != t.parent {
// XXX or verify this at Track time and require
// that update is passed only entries with the
......@@ -171,36 +258,33 @@ func (A PPTreeSubSet) xDifferenceInplace(B PPTreeSubSet) {
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)
}
func (A PPTreeSubSet) xUnionInplace(B PPTreeSubSet) {
func (A PPTreeSubSet) xDifferenceInplace(B PPTreeSubSet) {
if debugPPSet {
fmt.Printf("\n\n xUnionInplace:\n")
fmt.Printf("\n\n xDifferenceInplace:\n")
fmt.Printf(" a: %s\n", A)
fmt.Printf(" b: %s\n", B)
defer fmt.Printf(" ->u: %s\n", A)
defer fmt.Printf(" ->d: %s\n", A)
}
δnchild := map[zodb.Oid]int{}
// remove B.leafs and their parents
for oid, t2 := range B {
t, already := A[oid]
if !already {
t = &nodeInTree{parent: t2.parent, nchild: 0}
A[oid] = t
// remember to nchild++ in parent
if t.parent != zodb.InvalidOid {
δnchild[t.parent] += 1
if t2.nchild != 0 {
continue // not a leaf
}
} else {
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
......@@ -209,6 +293,10 @@ func (A PPTreeSubSet) xUnionInplace(B PPTreeSubSet) {
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
}
}
......@@ -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.
// XXX place
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