added string and int lists
This commit is contained in:
parent
9622f5745b
commit
9da371065d
@ -8,18 +8,18 @@ import (
|
||||
|
||||
// Route is a prefix with BGP information.
|
||||
type Route struct {
|
||||
ID string `json:"id"`
|
||||
NeighborID string `json:"neighbor_id"`
|
||||
ID string `json:"id"`
|
||||
NeighborID *string `json:"neighbor_id"`
|
||||
|
||||
Network string `json:"network"`
|
||||
Interface string `json:"interface"`
|
||||
Gateway string `json:"gateway"`
|
||||
Network *string `json:"network"`
|
||||
Interface *string `json:"interface"`
|
||||
Gateway *string `json:"gateway"`
|
||||
Metric int `json:"metric"`
|
||||
BGP *BGPInfo `json:"bgp"`
|
||||
Age time.Duration `json:"age"`
|
||||
Type []string `json:"type"` // [BGP, unicast, univ]
|
||||
Primary bool `json:"primary"`
|
||||
LearntFrom string `json:"learnt_from"`
|
||||
LearntFrom *string `json:"learnt_from"`
|
||||
|
||||
Details *json.RawMessage `json:"details"`
|
||||
}
|
||||
|
@ -1,93 +0,0 @@
|
||||
package pools
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// IntNode is a node in the tree.
|
||||
type IntNode struct {
|
||||
children []*IntNode
|
||||
value int
|
||||
counter int
|
||||
ptr []int
|
||||
}
|
||||
|
||||
// Internally acquire list by traversing the tree and
|
||||
// creating nodes if required.
|
||||
func (n *IntNode) traverse(list, tail []int) []int {
|
||||
head := tail[0]
|
||||
tail = tail[1:]
|
||||
|
||||
// Seek for value in children
|
||||
var child *IntNode
|
||||
for _, c := range n.children {
|
||||
if c.value == head {
|
||||
child = c
|
||||
}
|
||||
}
|
||||
if child == nil {
|
||||
// Insert child
|
||||
child = &IntNode{
|
||||
children: []*IntNode{},
|
||||
value: head,
|
||||
ptr: nil,
|
||||
}
|
||||
n.children = append(n.children, child)
|
||||
}
|
||||
|
||||
// Set list ptr if required
|
||||
if len(tail) == 0 {
|
||||
if child.ptr == nil {
|
||||
child.ptr = list
|
||||
}
|
||||
return child.ptr
|
||||
}
|
||||
|
||||
return child.traverse(list, tail)
|
||||
}
|
||||
|
||||
// IntTree is a tree structure for deduplicating
|
||||
// lists of integers.
|
||||
type IntTree struct {
|
||||
root *IntNode
|
||||
}
|
||||
|
||||
// NewIntTree initializes an empty int tree
|
||||
func NewIntTree() *IntTree {
|
||||
return &IntTree{
|
||||
root: &IntNode{
|
||||
ptr: []int{},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Acquire int list element
|
||||
func (t *IntTree) Acquire(list []int) []int {
|
||||
if len(list) == 0 {
|
||||
return t.root.ptr // root
|
||||
}
|
||||
return t.root.traverse(list, list)
|
||||
}
|
||||
|
||||
// A IntList pool can be used to deduplicate
|
||||
// lists of integers. Like an AS path.
|
||||
//
|
||||
// A Tree datastructure is used.
|
||||
type IntList struct {
|
||||
values *IntTree
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// NewIntList creates a new int list pool
|
||||
func NewIntList() *IntList {
|
||||
return &IntList{
|
||||
values: NewIntTree(),
|
||||
}
|
||||
}
|
||||
|
||||
// Acquire int list from pool
|
||||
func (p *IntList) Acquire(list []int) []int {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
return p.values.Acquire(list)
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package pools
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// A IntListList pool can be used to deduplicate
|
||||
// lists of lists of integers. Like a list of large
|
||||
// BGP communities.
|
||||
//
|
||||
// A Tree datastructure is used.
|
||||
type IntListList struct {
|
||||
lists *IntTree
|
||||
ptrs *IntTree
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// NewIntListList creates a new int list pool
|
||||
func NewIntListList() *IntListList {
|
||||
return &IntListList{
|
||||
lists: NewIntTree(),
|
||||
ptrs: NewIntTree(),
|
||||
}
|
||||
}
|
||||
|
||||
// Acquire int list from pool
|
||||
func (p *IntListList) Acquire(list [][]int) [][]int {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
|
||||
// Convert list of list to list of ptrs
|
||||
ptrList := make([]int, len(list))
|
||||
for i, v := range list {
|
||||
ptr := p.ptrs.Acquire(v)
|
||||
ptrV := int(uintptr(reflect.ValueOf(ptr).UnsafePointer()))
|
||||
ptrList[i] = ptrV
|
||||
}
|
||||
|
||||
return []int{}
|
||||
}
|
119
pkg/store/pools/lists.go
Normal file
119
pkg/store/pools/lists.go
Normal file
@ -0,0 +1,119 @@
|
||||
package pools
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Node is a node in the tree.
|
||||
type Node struct {
|
||||
children []*Node
|
||||
value int
|
||||
counter int
|
||||
ptr interface{}
|
||||
}
|
||||
|
||||
// Internally acquire list by traversing the tree and
|
||||
// creating nodes if required.
|
||||
func (n *Node) traverse(list interface{}, tail []int) interface{} {
|
||||
head := tail[0]
|
||||
tail = tail[1:]
|
||||
|
||||
// Seek for value in children
|
||||
var child *Node
|
||||
for _, c := range n.children {
|
||||
if c.value == head {
|
||||
child = c
|
||||
}
|
||||
}
|
||||
if child == nil {
|
||||
// Insert child
|
||||
child = &Node{
|
||||
children: []*Node{},
|
||||
value: head,
|
||||
ptr: nil,
|
||||
}
|
||||
n.children = append(n.children, child)
|
||||
}
|
||||
|
||||
// Set list ptr if required
|
||||
if len(tail) == 0 {
|
||||
if child.ptr == nil {
|
||||
child.ptr = list
|
||||
}
|
||||
return child.ptr
|
||||
}
|
||||
|
||||
return child.traverse(list, tail)
|
||||
}
|
||||
|
||||
// A IntList pool can be used to deduplicate
|
||||
// lists of integers. Like an AS path.
|
||||
//
|
||||
// A Tree datastructure is used.
|
||||
type IntList struct {
|
||||
root *Node
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// NewIntList creates a new int list pool
|
||||
func NewIntList() *IntList {
|
||||
return &IntList{
|
||||
root: &Node{
|
||||
ptr: []int{},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Acquire int list from pool
|
||||
func (p *IntList) Acquire(list []int) []int {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
|
||||
if len(list) == 0 {
|
||||
return p.root.ptr.([]int) // root
|
||||
}
|
||||
return p.root.traverse(list, list).([]int)
|
||||
}
|
||||
|
||||
// A StringList pool can be used for deduplicating lists
|
||||
// of strings. (This is a variant of an int list, as string
|
||||
// values are converted to int.
|
||||
type StringList struct {
|
||||
root *Node
|
||||
values map[string]int
|
||||
head int
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// NewStringList creates a new string list.
|
||||
func NewStringList() *StringList {
|
||||
return &StringList{
|
||||
head: 1,
|
||||
values: map[string]int{},
|
||||
root: &Node{
|
||||
ptr: []string{},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Acquire the string list pointer from the pool
|
||||
func (p *StringList) Acquire(list []string) []string {
|
||||
if len(list) == 0 {
|
||||
return p.root.ptr.([]string) // root
|
||||
}
|
||||
|
||||
// Make idenfier list
|
||||
id := make([]int, len(list))
|
||||
for i, s := range list {
|
||||
// Resolve string value into int
|
||||
v, ok := p.values[s]
|
||||
if !ok {
|
||||
p.head++
|
||||
p.values[s] = p.head
|
||||
v = p.head
|
||||
}
|
||||
id[i] = v
|
||||
}
|
||||
|
||||
return p.root.traverse(list, id).([]string)
|
||||
}
|
@ -43,3 +43,16 @@ func TestPtrIntList(t *testing.T) {
|
||||
|
||||
t.Log(fmt.Sprintf("P: %x %x %v", int(uintptr(ra)), rb, ra == rb))
|
||||
}
|
||||
|
||||
func TestAcquireStringList(t *testing.T) {
|
||||
q := []string{"foo", "bar", "bgp"}
|
||||
w := []string{"foo", "bar", "bgp"}
|
||||
e := []string{"foo", "bpf"}
|
||||
|
||||
p2 := NewStringList()
|
||||
x1 := p2.Acquire(q)
|
||||
x2 := p2.Acquire(w)
|
||||
x3 := p2.Acquire(e)
|
||||
fmt.Printf("Ptr: %p %p => %p %p\n", q, w, x1, x2)
|
||||
fmt.Printf("Ptr: %p => %p\n", e, x3)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user