Commit 2e9e5cab authored by Kirill Smelkov's avatar Kirill Smelkov

go/zodb/btree: Verify that BTree children are always all of the same kind

They are all either BTree or all Buckets.

See https://github.com/zopefoundation/ZODB/blob/3.10.7-4-gb8d7a8567/src/BTrees/Development.txt#L231
for details
parent 50f570c8
...@@ -331,6 +331,7 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) { ...@@ -331,6 +331,7 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) {
n := (len(t) + 1) / 2 n := (len(t) + 1) / 2
bt.data = make([]_BTreeItem, 0, n) bt.data = make([]_BTreeItem, 0, n)
var kprev int64 var kprev int64
var childrenKind int // 1 - BTree, 2 - Bucket
for i, idx := 0, 0; i < n; i++ { for i, idx := 0, 0; i < n; i++ {
key := int64(math.Min<Key>) // KEY(-) (qualifies for ) key := int64(math.Min<Key>) // KEY(-) (qualifies for )
if i > 0 { if i > 0 {
...@@ -354,12 +355,23 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) { ...@@ -354,12 +355,23 @@ func (bt *btreeState) PySetState(pystate interface{}) (err error) {
} }
kprev = key kprev = key
// check all children are of the same type
var kind int // see childrenKind ^^^
switch child.(type) { switch child.(type) {
default: default:
return fmt.Errorf("data: [%d]: child must be BTree|Bucket; got %T", i, child) return fmt.Errorf("data: [%d]: child must be BTree|Bucket; got %T", i, child)
case *BTree: // ok case *BTree:
case *Bucket: // ok kind = 1
case *Bucket:
kind = 2
}
if i == 0 {
childrenKind = kind
}
if kind != childrenKind {
fmt.Errorf("data: [%d]: children must be of the same type", i)
} }
bt.data = append(bt.data, _BTreeItem{key: kkey, child: child}) bt.data = append(bt.data, _BTreeItem{key: kkey, child: child})
......
...@@ -333,6 +333,7 @@ func (bt *iobtreeState) PySetState(pystate interface{}) (err error) { ...@@ -333,6 +333,7 @@ func (bt *iobtreeState) PySetState(pystate interface{}) (err error) {
n := (len(t) + 1) / 2 n := (len(t) + 1) / 2
bt.data = make([]_IOBTreeItem, 0, n) bt.data = make([]_IOBTreeItem, 0, n)
var kprev int64 var kprev int64
var childrenKind int // 1 - IOBTree, 2 - IOBucket
for i, idx := 0, 0; i < n; i++ { for i, idx := 0, 0; i < n; i++ {
key := int64(math.MinInt32) // int32(-∞) (qualifies for ≤) key := int64(math.MinInt32) // int32(-∞) (qualifies for ≤)
if i > 0 { if i > 0 {
...@@ -356,12 +357,23 @@ func (bt *iobtreeState) PySetState(pystate interface{}) (err error) { ...@@ -356,12 +357,23 @@ func (bt *iobtreeState) PySetState(pystate interface{}) (err error) {
} }
kprev = key kprev = key
// check all children are of the same type
var kind int // see childrenKind ^^^
switch child.(type) { switch child.(type) {
default: default:
return fmt.Errorf("data: [%d]: child must be IOBTree|IOBucket; got %T", i, child) return fmt.Errorf("data: [%d]: child must be IOBTree|IOBucket; got %T", i, child)
case *IOBTree: // ok case *IOBTree:
case *IOBucket: // ok kind = 1
case *IOBucket:
kind = 2
}
if i == 0 {
childrenKind = kind
}
if kind != childrenKind {
fmt.Errorf("data: [%d]: children must be of the same type", i)
} }
bt.data = append(bt.data, _IOBTreeItem{key: kkey, child: child}) bt.data = append(bt.data, _IOBTreeItem{key: kkey, child: child})
......
...@@ -333,6 +333,7 @@ func (bt *lobtreeState) PySetState(pystate interface{}) (err error) { ...@@ -333,6 +333,7 @@ func (bt *lobtreeState) PySetState(pystate interface{}) (err error) {
n := (len(t) + 1) / 2 n := (len(t) + 1) / 2
bt.data = make([]_LOBTreeItem, 0, n) bt.data = make([]_LOBTreeItem, 0, n)
var kprev int64 var kprev int64
var childrenKind int // 1 - LOBTree, 2 - LOBucket
for i, idx := 0, 0; i < n; i++ { for i, idx := 0, 0; i < n; i++ {
key := int64(math.MinInt64) // int64(-∞) (qualifies for ≤) key := int64(math.MinInt64) // int64(-∞) (qualifies for ≤)
if i > 0 { if i > 0 {
...@@ -356,12 +357,23 @@ func (bt *lobtreeState) PySetState(pystate interface{}) (err error) { ...@@ -356,12 +357,23 @@ func (bt *lobtreeState) PySetState(pystate interface{}) (err error) {
} }
kprev = key kprev = key
// check all children are of the same type
var kind int // see childrenKind ^^^
switch child.(type) { switch child.(type) {
default: default:
return fmt.Errorf("data: [%d]: child must be LOBTree|LOBucket; got %T", i, child) return fmt.Errorf("data: [%d]: child must be LOBTree|LOBucket; got %T", i, child)
case *LOBTree: // ok case *LOBTree:
case *LOBucket: // ok kind = 1
case *LOBucket:
kind = 2
}
if i == 0 {
childrenKind = kind
}
if kind != childrenKind {
fmt.Errorf("data: [%d]: children must be of the same type", i)
} }
bt.data = append(bt.data, _LOBTreeItem{key: kkey, child: child}) bt.data = append(bt.data, _LOBTreeItem{key: kkey, child: child})
......
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