Skip to content

Commit

Permalink
rethink iterator generators and table init state
Browse files Browse the repository at this point in the history
- don't init uninitialized table
- simplify code
  • Loading branch information
gaissmai committed Aug 29, 2024
1 parent 0f0814d commit e9c25a8
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 61 deletions.
18 changes: 0 additions & 18 deletions node.go
Original file line number Diff line number Diff line change
Expand Up @@ -563,21 +563,3 @@ func (n *node[V]) allRecSorted(path [16]byte, depth int, is4 bool, yield func(ne

return true
}

// numPrefixesRec, calculate the number of prefixes under n.
func (n *node[V]) numPrefixesRec() int {
size := len(n.prefixes) // this node
for _, c := range n.children {
size += c.numPrefixesRec()
}
return size
}

// numNodesRec, calculate the number of nodes under n.
func (n *node[V]) numNodesRec() int {
size := 1 // this node
for _, c := range n.children {
size += c.numNodesRec()
}
return size
}
13 changes: 13 additions & 0 deletions node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ import (
"testing"
)

// numNodesRec, calculate the number of nodes under n.
func (n *node[V]) numNodesRec() int {
if n == nil {
return 0
}

size := 1 // this node
for _, c := range n.children {
size += c.numNodesRec()
}
return size
}

func TestInverseIndex(t *testing.T) {
t.Parallel()
for i := range maxNodeChildren {
Expand Down
29 changes: 2 additions & 27 deletions table.go
Original file line number Diff line number Diff line change
Expand Up @@ -531,22 +531,6 @@ func (t *Table[V]) OverlapsPrefix(pfx netip.Prefix) bool {
// Overlaps reports whether any IP in the table is matched by a route in the
// other table or vice versa.
func (t *Table[V]) Overlaps(o *Table[V]) bool {
if t.Size() == 0 || o.Size() == 0 {
return false
}

// t and o are already intialized (size != 0)

// at least one v4 is empty
if t.size4 == 0 || o.size4 == 0 {
return t.Overlaps6(o)
}

// at least one v6 is empty
if t.size6 == 0 || o.size6 == 0 {
return t.Overlaps4(o)
}

return t.Overlaps4(o) || t.Overlaps6(o)
}

Expand All @@ -557,7 +541,7 @@ func (t *Table[V]) Overlaps4(o *Table[V]) bool {
return false
}

// t and o are already intialized (size != 0)
// t and o are already intialized (size4 != 0)
return t.root4.overlapsRec(o.root4)
}

Expand All @@ -568,7 +552,7 @@ func (t *Table[V]) Overlaps6(o *Table[V]) bool {
return false
}

// t and o are already intialized (size != 0)
// t and o are already intialized (size6 != 0)
return t.root6.overlapsRec(o.root6)
}

Expand Down Expand Up @@ -629,12 +613,3 @@ func (t *Table[V]) Size4() int {
func (t *Table[V]) Size6() int {
return t.size6
}

// nodes, calculates the IPv4 and IPv6 nodes and returns the sum.
func (t *Table[V]) nodes() int {
if !t.isInit() {
return 0
}

return t.root4.numNodesRec() + t.root6.numNodesRec()
}
30 changes: 24 additions & 6 deletions table_iter.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,48 +139,66 @@ func (t *Table[V]) Subnets(pfx netip.Prefix) func(yield func(netip.Prefix, V) bo
// is not specified and is not guaranteed to be the same from one call to the
// next.
func (t *Table[V]) All() func(yield func(pfx netip.Prefix, val V) bool) {
t.init()
return func(yield func(netip.Prefix, V) bool) {
if !t.isInit() {
return
}

_ = t.root4.allRec(zeroPath, 0, true, yield) && t.root6.allRec(zeroPath, 0, false, yield)
}
}

// All4, like [Table.All] but only for the v4 routing table.
func (t *Table[V]) All4() func(yield func(pfx netip.Prefix, val V) bool) {
t.init()
return func(yield func(netip.Prefix, V) bool) {
if !t.isInit() {
return
}

_ = t.root4.allRec(zeroPath, 0, true, yield)
}
}

// All6, like [Table.All] but only for the v6 routing table.
func (t *Table[V]) All6() func(yield func(pfx netip.Prefix, val V) bool) {
t.init()
return func(yield func(netip.Prefix, V) bool) {
if !t.isInit() {
return
}

_ = t.root6.allRec(zeroPath, 0, false, yield)
}
}

// AllSorted returns an iterator over key-value pairs from Table in natural CIDR sort order.
func (t *Table[V]) AllSorted() func(yield func(pfx netip.Prefix, val V) bool) {
t.init()
return func(yield func(netip.Prefix, V) bool) {
if !t.isInit() {
return
}

_ = t.root4.allRecSorted(zeroPath, 0, true, yield) && t.root6.allRecSorted(zeroPath, 0, false, yield)
}
}

// AllSorted4, like [Table.AllSorted] but only for the v4 routing table.
func (t *Table[V]) AllSorted4() func(yield func(pfx netip.Prefix, val V) bool) {
t.init()
return func(yield func(netip.Prefix, V) bool) {
if !t.isInit() {
return
}

_ = t.root4.allRecSorted(zeroPath, 0, true, yield)
}
}

// AllSorted6, like [Table.AllSorted] but only for the v6 routing table.
func (t *Table[V]) AllSorted6() func(yield func(pfx netip.Prefix, val V) bool) {
t.init()
return func(yield func(netip.Prefix, V) bool) {
if !t.isInit() {
return
}

_ = t.root6.allRecSorted(zeroPath, 0, false, yield)
}
}
45 changes: 45 additions & 0 deletions table_iter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,51 @@ import (
"testing"
)

func TestTableIsEmptyIterators(t *testing.T) {
rt := new(Table[byte])

_ = rt.All()
if rt.isInit() {
t.Error("All() changed the init state of Table")
}

_ = rt.All4()
if rt.isInit() {
t.Error("All4() changed the init state of Table")
}

_ = rt.All6()
if rt.isInit() {
t.Error("All6() changed the init state of Table")
}

_ = rt.AllSorted()
if rt.isInit() {
t.Error("AllSorted() changed the init state of Table")
}

_ = rt.AllSorted4()
if rt.isInit() {
t.Error("AllSorted4() changed the init state of Table")
}

_ = rt.AllSorted6()
if rt.isInit() {
t.Error("AllSorted6() changed the init state of Table")
}

pfx := mpp("1.2.3.4/32")
_ = rt.Subnets(pfx)
if rt.isInit() {
t.Error("Subnets() changed the init state of Table")
}

_ = rt.Supernets(pfx)
if rt.isInit() {
t.Error("Supernets() changed the init state of Table")
}
}

func TestAll4RangeOverFunc(t *testing.T) {
pfxs := randomPrefixes4(10_000)
seen := make(map[netip.Prefix]int, 10_000)
Expand Down
15 changes: 5 additions & 10 deletions table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ var mpa = netip.MustParseAddr

var mpp = netip.MustParsePrefix

// nodes, calculates the nodes.
func (t *Table[V]) nodes() int {
return t.root4.numNodesRec() + t.root6.numNodesRec()
}

// ############ tests ################################

func TestInvalidPrefix(t *testing.T) {
Expand Down Expand Up @@ -1726,16 +1731,6 @@ func TestSize(t *testing.T) {
if golden6 != rtbl.Size6() {
t.Errorf("Size6: want: %d, got: %d", golden6, rtbl.Size6())
}

size4Rec := rtbl.root4.numPrefixesRec()
if golden4 != size4Rec {
t.Errorf("size4Rec: want: %d, got: %d", golden4, size4Rec)
}

size6Rec := rtbl.root6.numPrefixesRec()
if golden6 != size6Rec {
t.Errorf("size6Rec: want: %d, got: %d", golden6, size6Rec)
}
}

// ############ benchmarks ################################
Expand Down

0 comments on commit e9c25a8

Please sign in to comment.