Commit 66bc41ce authored by Kirill Smelkov's avatar Kirill Smelkov

X Fix bug in PPTreeSubSet.Difference - it was always leaving root node alive

So that even A \ A was not ø.
parent 7533257b
...@@ -27,6 +27,7 @@ import ( ...@@ -27,6 +27,7 @@ import (
) )
const tracePPSet = false const tracePPSet = false
const debugPPSet = false
// PPTreeSubSet represents PP-connected subset of tree node objects. // PPTreeSubSet represents PP-connected subset of tree node objects.
// //
...@@ -291,10 +292,16 @@ func (A PPTreeSubSet) fixup(δnchild map[zodb.Oid]int) { ...@@ -291,10 +292,16 @@ func (A PPTreeSubSet) fixup(δnchild map[zodb.Oid]int) {
A.xfixup(+1, δnchild) A.xfixup(+1, δnchild)
} }
func (A PPTreeSubSet) xfixup(sign int, δnchild map[zodb.Oid]int) { func (A PPTreeSubSet) xfixup(sign int, δnchild map[zodb.Oid]int) {
//fmt.Printf("\nfixup:\n") if debugPPSet {
//fmt.Printf(" ·: %s\n", A) ssign := "+"
//fmt.Printf(" δ: %v\n", δnchild) if sign < 0 {
//defer fmt.Printf(" ->·: %s\n\n", A) ssign = "-"
}
fmt.Printf("\n fixup:\n")
fmt.Printf(" ·: %s\n", A)
fmt.Printf(" %sδ: %v\n", ssign, δnchild)
defer fmt.Printf(" ->·: %s\n\n", A)
}
gcq := []zodb.Oid{} gcq := []zodb.Oid{}
for oid, δnc := range δnchild { for oid, δnc := range δnchild {
...@@ -326,7 +333,8 @@ func (S PPTreeSubSet) gc1(oid zodb.Oid) { ...@@ -326,7 +333,8 @@ func (S PPTreeSubSet) gc1(oid zodb.Oid) {
for oid != zodb.InvalidOid { for oid != zodb.InvalidOid {
t := S[oid] t := S[oid]
t.nchild-- t.nchild--
if t.nchild > 0 || /* root node */t.parent == zodb.InvalidOid { // if t.nchild > 0 || /* root node */t.parent == zodb.InvalidOid {
if t.nchild > 0 {
break break
} }
delete(S, oid) delete(S, oid)
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
package xbtree package xbtree
import ( import (
"strings"
"testing" "testing"
"lab.nexedi.com/kirr/neo/go/zodb" "lab.nexedi.com/kirr/neo/go/zodb"
...@@ -79,19 +80,43 @@ func TestPPTreeSubSetOps(t *testing.T) { ...@@ -79,19 +80,43 @@ func TestPPTreeSubSetOps(t *testing.T) {
S{a:{ø,1}, b:{a,0}}, // B S{a:{ø,1}, b:{a,0}}, // B
S{a:{ø,1}, b:{a,0}}, // U S{a:{ø,1}, b:{a,0}}, // U
S{}), // D S{}), // D
}
for _, tt := range testv { E(
U := tt.A.Union(tt.B) S{a:{ø,1}, b:{a,1}, c:{b,0}}, // A
D := tt.A.Difference(tt.B) S{a:{ø,1}, b:{a,1}, c:{b,0}}, // B (=A)
S{a:{ø,1}, b:{a,1}, c:{b,0}}, // U (=A)
S{}), // D
}
if !U.Equal(tt.Union) { assert1 := func(op string, A, B, res, resOK S) {
t.Errorf("Union:\n A: %s\n B: %s\n ->u: %s\n okU: %s\n", tt.A, tt.B, U, tt.Union) t.Helper()
if res.Equal(resOK) {
return
} }
if !D.Equal(tt.Difference) { op1 := op[0:1]
t.Errorf("Difference:\n A: %s\n B: %s\n ->d: %s\n okD: %s\n", tt.A, tt.B, D, tt.Difference) t.Errorf("%s:\n A: %s\n B: %s\n ->%s: %s\n ok%s: %s\n",
strings.Title(op), A, B, op1, res, strings.ToUpper(op1), resOK)
} }
for _, tt := range testv {
Uab := tt.A.Union(tt.B)
Uba := tt.B.Union(tt.A)
Dab := tt.A.Difference(tt.B)
assert1("union", tt.A, tt.B, Uab, tt.Union)
assert1("union", tt.B, tt.A, Uba, tt.Union)
assert1("difference", tt.A, tt.B, Dab, tt.Difference)
Uaa := tt.A.Union(tt.A)
Ubb := tt.B.Union(tt.B)
Daa := tt.A.Difference(tt.A)
Dbb := tt.B.Difference(tt.B)
assert1("union", tt.A, tt.A, Uaa, tt.A)
assert1("union", tt.B, tt.B, Ubb, tt.B)
assert1("difference", tt.A, tt.A, Daa, S{})
assert1("difference", tt.B, tt.B, Dbb, S{})
// XXX also verify U/D properties like (A+B)\B + (A+B)\A + (A^B) == (A+B) ? // XXX also verify U/D properties like (A+B)\B + (A+B)\A + (A^B) == (A+B) ?
} }
} }
...@@ -159,7 +159,7 @@ func δZConnectTracked(δZv []zodb.Oid, T PPTreeSubSet) (δZTC SetOid, δtopsByR ...@@ -159,7 +159,7 @@ func δZConnectTracked(δZv []zodb.Oid, T PPTreeSubSet) (δZTC SetOid, δtopsByR
// nodeInRange represents a Node coming under [lo, hi_] key range in its tree. // nodeInRange represents a Node coming under [lo, hi_] key range in its tree.
type nodeInRange struct { type nodeInRange struct {
prefix []zodb.Oid // path to this node goes via this objects prefix []zodb.Oid // path to this node goes via this objects
lo, hi_ Key // [lo, hi_] NOTE _not_ hi) not to overflow at ∞ XXX -> Range lo, hi_ Key // [lo, hi_] NOTE _not_ hi) not to overflow at ∞ XXX -> keycov KeyRange?
node Node node Node
done bool // whether this node was already taken into account while computing diff done bool // whether this node was already taken into account while computing diff
} }
......
...@@ -1042,11 +1042,7 @@ func xverifyΔBTail_rebuild(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, t0, t1 ...@@ -1042,11 +1042,7 @@ func xverifyΔBTail_rebuild(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, t0, t1
} }
} }
// // tracked keys1 becomes tracked keys1_2 after Update(t1->t2)
//// keys1_2 := kadj12.Map(keys1)
// keys1_2 := kadj12.Map(kadj01.Map(keys1_0))
xverifyΔBTail_rebuild_U(t, δbtail, db, treeRoot, t1, t2, xat, xverifyΔBTail_rebuild_U(t, δbtail, db, treeRoot, t1, t2, xat,
// /*trackSet=*/t2.xkv.trackSet(keys1_2),
/*trackSet=*/t2.xkv.trackSet(keys1R2), /*trackSet=*/t2.xkv.trackSet(keys1R2),
/*vδT=*/ δkv1_k1R2, δkv2_k1R2) /*vδT=*/ δkv1_k1R2, δkv2_k1R2)
...@@ -1070,23 +1066,22 @@ func xverifyΔBTail_rebuild(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, t0, t1 ...@@ -1070,23 +1066,22 @@ func xverifyΔBTail_rebuild(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, t0, t1
keys12R2 = keys12R2_ keys12R2 = keys12R2_
} }
// // δkv1_2 = t1.δxkv / kadj10(kadj21(kadj12(keys1) | keys2)) ///*
// // δkv2_2 = t2.δxkv / kadj10(kadj21(kadj12(keys1) | keys2))
//// keys12_2 := keys1_2.Union(keys2)
//// keys12_0 := kadj10.Map(kadj21.Map(keys12_2))
/*
fmt.Printf("\n\n\nKKK\nkeys1=%s keys2=%s\n", keys1, keys2) fmt.Printf("\n\n\nKKK\nkeys1=%s keys2=%s\n", keys1, keys2)
fmt.Printf("keys12R2=%s\n", keys12R2) fmt.Printf("keys1R2: %s\n", keys1R2)
fmt.Printf("keys12R2: %s\n", keys12R2)
fmt.Printf("t0.xkv: %v\n", t0.xkv) fmt.Printf("t0.xkv: %v\n", t0.xkv)
fmt.Printf("t1.xkv: %v\n", t1.xkv) fmt.Printf("t1.xkv: %v\n", t1.xkv)
fmt.Printf("t2.xkv: %v\n", t2.xkv) fmt.Printf("t2.xkv: %v\n", t2.xkv)
fmt.Printf("kadj21: %v\n", kadj21) fmt.Printf("kadj21: %v\n", kadj21)
fmt.Printf("kadj12: %v\n", kadj12) fmt.Printf("kadj12: %v\n", kadj12)
fmt.Printf("t2.xkv.trackSet(%s) -> %s", keys12R2, t2.xkv.trackSet(keys12R2)) fmt.Printf("t2.xkv.trackSet(keys2) -> %s\n", t2.xkv.trackSet(keys2))
fmt.Printf("t2.xkv.trackSet(keys1R2) -> %s\n", t2.xkv.trackSet(keys1R2))
fmt.Printf("t2.xkv.trackSet(keys2) \\ t2.xkv.trackSet(keys1R2) -> %s\n",
t2.xkv.trackSet(keys2).Difference(t2.xkv.trackSet(keys1R2)))
fmt.Printf("\n\n\n") fmt.Printf("\n\n\n")
*/ //*/
// δkvX_k12R2 = tX.δxkv / keys12R2 // δkvX_k12R2 = tX.δxkv / keys12R2
...@@ -1109,12 +1104,10 @@ func xverifyΔBTail_rebuild(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, t0, t1 ...@@ -1109,12 +1104,10 @@ func xverifyΔBTail_rebuild(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, t0, t1
xverifyΔBTail_rebuild_TR(t, db, δbtail_, t2, treeRoot, xat, xverifyΔBTail_rebuild_TR(t, db, δbtail_, t2, treeRoot, xat,
// after Track(keys2) // after Track(keys2)
keys2, keys2,
// /*trackSet*/ t2.xkv.trackSet(keys1_2),
/*trackSet*/ t2.xkv.trackSet(keys1R2), /*trackSet*/ t2.xkv.trackSet(keys1R2),
/*trackNew*/ t2.xkv.trackSet(keys2).Difference( /*trackNew*/ t2.xkv.trackSet(keys2).Difference(
// trackNew should not cover ranges that are // trackNew should not cover ranges that are
// already in trackSet // already in trackSet
// t2.xkv.trackSet(keys1_2)),
t2.xkv.trackSet(keys1R2)), t2.xkv.trackSet(keys1R2)),
// after rebuild // after rebuild
......
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