improved add filter performance
This commit is contained in:
parent
cbdc1f5d67
commit
bf95c539ce
@ -1,7 +1,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -163,20 +163,26 @@ type RouteServersResponse struct {
|
|||||||
type Community []int
|
type Community []int
|
||||||
|
|
||||||
func (com Community) String() string {
|
func (com Community) String() string {
|
||||||
res := ""
|
|
||||||
if len(com) < 1 {
|
if len(com) < 1 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
for _, v := range com {
|
s := ""
|
||||||
res += fmt.Sprintf(":%d", v)
|
for i, v := range com {
|
||||||
|
if i > 0 {
|
||||||
|
s += ":"
|
||||||
|
}
|
||||||
|
s += strconv.Itoa(v)
|
||||||
}
|
}
|
||||||
return res[1:]
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Communities is a collection of bgp communities
|
// Communities is a collection of bgp communities
|
||||||
type Communities []Community
|
type Communities []Community
|
||||||
|
|
||||||
// Unique deduplicates communities
|
// Unique deduplicates communities.
|
||||||
|
/*
|
||||||
|
We can skip this. Worst case is, that the
|
||||||
|
cardinality is off.
|
||||||
func (communities Communities) Unique() Communities {
|
func (communities Communities) Unique() Communities {
|
||||||
seen := map[string]bool{}
|
seen := map[string]bool{}
|
||||||
result := make(Communities, 0, len(communities))
|
result := make(Communities, 0, len(communities))
|
||||||
@ -192,25 +198,34 @@ func (communities Communities) Unique() Communities {
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// ExtCommunity is a BGP extended community
|
// ExtCommunity is a BGP extended community
|
||||||
type ExtCommunity []interface{}
|
type ExtCommunity []interface{}
|
||||||
|
|
||||||
func (com ExtCommunity) String() string {
|
func (com ExtCommunity) String() string {
|
||||||
res := ""
|
|
||||||
if len(com) < 1 {
|
if len(com) < 1 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
for _, v := range com {
|
res := ""
|
||||||
res += fmt.Sprintf(":%v", v)
|
for i, v := range com {
|
||||||
|
if i == 0 {
|
||||||
|
res += v.(string)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if i > 0 {
|
||||||
|
res += ":"
|
||||||
|
}
|
||||||
|
res += strconv.Itoa(v.(int))
|
||||||
}
|
}
|
||||||
return res[1:]
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtCommunities is a collection of extended bgp communities.
|
// ExtCommunities is a collection of extended bgp communities.
|
||||||
type ExtCommunities []ExtCommunity
|
type ExtCommunities []ExtCommunity
|
||||||
|
|
||||||
// Unique deduplicates extended communities.
|
// Unique deduplicates extended communities.
|
||||||
|
/*
|
||||||
func (communities ExtCommunities) Unique() ExtCommunities {
|
func (communities ExtCommunities) Unique() ExtCommunities {
|
||||||
seen := map[string]bool{}
|
seen := map[string]bool{}
|
||||||
result := make(ExtCommunities, 0, len(communities))
|
result := make(ExtCommunities, 0, len(communities))
|
||||||
@ -226,6 +241,7 @@ func (communities ExtCommunities) Unique() ExtCommunities {
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// BGPInfo is a set of BGP attributes
|
// BGPInfo is a set of BGP attributes
|
||||||
type BGPInfo struct {
|
type BGPInfo struct {
|
||||||
|
@ -74,7 +74,7 @@ func TestCommunityStringify(t *testing.T) {
|
|||||||
t.Error("Expected 23:42, got:", com.String())
|
t.Error("Expected 23:42, got:", com.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
extCom := ExtCommunity{"ro", "42", "123"}
|
extCom := ExtCommunity{"ro", 42, 123}
|
||||||
if extCom.String() != "ro:42:123" {
|
if extCom.String() != "ro:42:123" {
|
||||||
t.Error("Expected ro:42:123, but got:", extCom.String())
|
t.Error("Expected ro:42:123, but got:", extCom.String())
|
||||||
}
|
}
|
||||||
@ -134,6 +134,7 @@ func TestHasCommunity(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func TestUniqueCommunities(t *testing.T) {
|
func TestUniqueCommunities(t *testing.T) {
|
||||||
all := Communities{Community{23, 42}, Community{42, 123}, Community{23, 42}}
|
all := Communities{Community{23, 42}, Community{42, 123}, Community{23, 42}}
|
||||||
unique := all.Unique()
|
unique := all.Unique()
|
||||||
@ -154,3 +155,4 @@ func TestUniqueExtCommunities(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Log("All:", all, "Unique:", unique)
|
t.Log("All:", all, "Unique:", unique)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -131,14 +130,27 @@ func (g *SearchFilterGroup) Contains(filter *SearchFilter) bool {
|
|||||||
return g.FindFilter(filter) != nil
|
return g.FindFilter(filter) != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// filterValueAsString gets the string representation
|
||||||
|
// from a filter value
|
||||||
|
func filterValueAsString(value interface{}) string {
|
||||||
|
switch v := value.(type) {
|
||||||
|
case int:
|
||||||
|
return strconv.Itoa(v)
|
||||||
|
case string:
|
||||||
|
return v
|
||||||
|
case Community:
|
||||||
|
return v.String()
|
||||||
|
case ExtCommunity:
|
||||||
|
return v.String()
|
||||||
|
}
|
||||||
|
panic("unexpected filter value")
|
||||||
|
}
|
||||||
|
|
||||||
// GetFilterByValue retrieves a filter by matching
|
// GetFilterByValue retrieves a filter by matching
|
||||||
// a string representation of it's filter value.
|
// a string representation of it's filter value.
|
||||||
func (g *SearchFilterGroup) GetFilterByValue(value interface{}) *SearchFilter {
|
func (g *SearchFilterGroup) GetFilterByValue(value interface{}) *SearchFilter {
|
||||||
// I've tried it with .(fmt.Stringer), but int does not implement this...
|
ref := filterValueAsString(value)
|
||||||
// So whatever. I'm using the trick of letting Sprintf choose the right
|
idx, ok := g.filtersIdx[ref]
|
||||||
// conversion. If this is too expensive, we need to refactor this.
|
|
||||||
// TODO: profile this.
|
|
||||||
idx, ok := g.filtersIdx[fmt.Sprintf("%v", value)]
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil // We don't have this particular filter
|
return nil // We don't have this particular filter
|
||||||
}
|
}
|
||||||
@ -158,7 +170,8 @@ func (g *SearchFilterGroup) AddFilter(filter *SearchFilter) {
|
|||||||
idx := len(g.Filters)
|
idx := len(g.Filters)
|
||||||
filter.Cardinality = 1
|
filter.Cardinality = 1
|
||||||
g.Filters = append(g.Filters, filter)
|
g.Filters = append(g.Filters, filter)
|
||||||
g.filtersIdx[fmt.Sprintf("%v", filter.Value)] = idx
|
ref := filterValueAsString(filter.Value)
|
||||||
|
g.filtersIdx[ref] = idx
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddFilters adds a list of filters to a group.
|
// AddFilters adds a list of filters to a group.
|
||||||
@ -172,7 +185,8 @@ func (g *SearchFilterGroup) AddFilters(filters []*SearchFilter) {
|
|||||||
func (g *SearchFilterGroup) rebuildIndex() {
|
func (g *SearchFilterGroup) rebuildIndex() {
|
||||||
idx := make(map[string]int)
|
idx := make(map[string]int)
|
||||||
for i, filter := range g.Filters {
|
for i, filter := range g.Filters {
|
||||||
idx[fmt.Sprintf("%v", filter.Value)] = i
|
ref := filterValueAsString(filter.Value)
|
||||||
|
idx[ref] = i
|
||||||
}
|
}
|
||||||
g.filtersIdx = idx // replace index
|
g.filtersIdx = idx // replace index
|
||||||
}
|
}
|
||||||
@ -368,21 +382,21 @@ func (s *SearchFilters) UpdateFromLookupRoute(r *LookupRoute) {
|
|||||||
|
|
||||||
// Add communities
|
// Add communities
|
||||||
communities := s.GetGroupByKey(SearchKeyCommunities)
|
communities := s.GetGroupByKey(SearchKeyCommunities)
|
||||||
for _, c := range r.Route.BGP.Communities.Unique() {
|
for _, c := range r.Route.BGP.Communities {
|
||||||
communities.AddFilter(&SearchFilter{
|
communities.AddFilter(&SearchFilter{
|
||||||
Name: c.String(),
|
Name: c.String(),
|
||||||
Value: c,
|
Value: c,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
extCommunities := s.GetGroupByKey(SearchKeyExtCommunities)
|
extCommunities := s.GetGroupByKey(SearchKeyExtCommunities)
|
||||||
for _, c := range r.Route.BGP.ExtCommunities.Unique() {
|
for _, c := range r.Route.BGP.ExtCommunities {
|
||||||
extCommunities.AddFilter(&SearchFilter{
|
extCommunities.AddFilter(&SearchFilter{
|
||||||
Name: c.String(),
|
Name: c.String(),
|
||||||
Value: c,
|
Value: c,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
largeCommunities := s.GetGroupByKey(SearchKeyLargeCommunities)
|
largeCommunities := s.GetGroupByKey(SearchKeyLargeCommunities)
|
||||||
for _, c := range r.Route.BGP.LargeCommunities.Unique() {
|
for _, c := range r.Route.BGP.LargeCommunities {
|
||||||
largeCommunities.AddFilter(&SearchFilter{
|
largeCommunities.AddFilter(&SearchFilter{
|
||||||
Name: c.String(),
|
Name: c.String(),
|
||||||
Value: c,
|
Value: c,
|
||||||
@ -398,21 +412,21 @@ func (s *SearchFilters) UpdateFromRoute(r *Route) {
|
|||||||
|
|
||||||
// Add communities
|
// Add communities
|
||||||
communities := s.GetGroupByKey(SearchKeyCommunities)
|
communities := s.GetGroupByKey(SearchKeyCommunities)
|
||||||
for _, c := range r.BGP.Communities.Unique() {
|
for _, c := range r.BGP.Communities {
|
||||||
communities.AddFilter(&SearchFilter{
|
communities.AddFilter(&SearchFilter{
|
||||||
Name: c.String(),
|
Name: c.String(),
|
||||||
Value: c,
|
Value: c,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
extCommunities := s.GetGroupByKey(SearchKeyExtCommunities)
|
extCommunities := s.GetGroupByKey(SearchKeyExtCommunities)
|
||||||
for _, c := range r.BGP.ExtCommunities.Unique() {
|
for _, c := range r.BGP.ExtCommunities {
|
||||||
extCommunities.AddFilter(&SearchFilter{
|
extCommunities.AddFilter(&SearchFilter{
|
||||||
Name: c.String(),
|
Name: c.String(),
|
||||||
Value: c,
|
Value: c,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
largeCommunities := s.GetGroupByKey(SearchKeyLargeCommunities)
|
largeCommunities := s.GetGroupByKey(SearchKeyLargeCommunities)
|
||||||
for _, c := range r.BGP.LargeCommunities.Unique() {
|
for _, c := range r.BGP.LargeCommunities {
|
||||||
largeCommunities.AddFilter(&SearchFilter{
|
largeCommunities.AddFilter(&SearchFilter{
|
||||||
Name: c.String(),
|
Name: c.String(),
|
||||||
Value: c,
|
Value: c,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user