mirror of
https://github.com/alice-lg/birdwatcher.git
synced 2025-03-09 00:00:05 +01:00
use reader interface insteead of string copies (decreases memory footprint)
This commit is contained in:
parent
68ce3c8422
commit
f905c9c3de
3 changed files with 47 additions and 47 deletions
14
bird/bird.go
14
bird/bird.go
|
@ -1,7 +1,9 @@
|
|||
package bird
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -53,10 +55,16 @@ func toCache(key string, val Parsed) {
|
|||
Cache.Unlock()
|
||||
}
|
||||
|
||||
func Run(args string) ([]byte, error) {
|
||||
func Run(args string) (io.Reader, error) {
|
||||
args = "show " + args
|
||||
argsList := strings.Split(args, " ")
|
||||
return exec.Command(ClientConf.BirdCmd, argsList...).Output()
|
||||
|
||||
out, err := exec.Command(ClientConf.BirdCmd, argsList...).Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bytes.NewReader(out), nil
|
||||
}
|
||||
|
||||
func InstallRateLimitReset() {
|
||||
|
@ -93,7 +101,7 @@ func checkRateLimit() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func RunAndParse(cmd string, parser func([]byte) Parsed) (Parsed, bool) {
|
||||
func RunAndParse(cmd string, parser func(io.Reader) Parsed) (Parsed, bool) {
|
||||
if val, ok := fromCache(cmd); ok {
|
||||
return val, true
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package bird
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -93,44 +94,32 @@ func emptyLine(line string) bool {
|
|||
return len(strings.TrimSpace(line)) == 0
|
||||
}
|
||||
|
||||
func getLinesUnfiltered(input string) []string {
|
||||
lines := make([]string, 0)
|
||||
func getLines(reader io.Reader, excludeFilter func(string) bool) []string {
|
||||
lines := []string{}
|
||||
|
||||
reader := strings.NewReader(input)
|
||||
scanner := bufio.NewScanner(reader)
|
||||
|
||||
for scanner.Scan() {
|
||||
if excludeFilter != nil && excludeFilter(scanner.Text()) {
|
||||
continue
|
||||
}
|
||||
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
|
||||
return lines
|
||||
}
|
||||
|
||||
func getLinesFromString(input string) []string {
|
||||
lines := getLinesUnfiltered(input)
|
||||
|
||||
var filtered []string
|
||||
|
||||
for _, line := range lines {
|
||||
if !emptyLine(line) {
|
||||
filtered = append(filtered, line)
|
||||
}
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func getLines(input []byte) []string {
|
||||
return getLinesFromString(string(input))
|
||||
func getNonEmptyLines(reader io.Reader) []string {
|
||||
return getLines(reader, emptyLine)
|
||||
}
|
||||
|
||||
func specialLine(line string) bool {
|
||||
return (strings.HasPrefix(line, "BIRD") || strings.HasPrefix(line, "Access restricted"))
|
||||
}
|
||||
|
||||
func parseStatus(input []byte) Parsed {
|
||||
func parseStatus(reader io.Reader) Parsed {
|
||||
res := Parsed{}
|
||||
lines := getLines(input)
|
||||
lines := getNonEmptyLines(reader)
|
||||
|
||||
for _, line := range lines {
|
||||
if regex.status.startLine.MatchString(line) {
|
||||
|
@ -157,10 +146,10 @@ func parseStatus(input []byte) Parsed {
|
|||
return Parsed{"status": res}
|
||||
}
|
||||
|
||||
func parseProtocols(input []byte) Parsed {
|
||||
func parseProtocols(reader io.Reader) Parsed {
|
||||
res := Parsed{}
|
||||
protocols := []string{}
|
||||
lines := getLinesUnfiltered(string(input))
|
||||
lines := getLines(reader, nil)
|
||||
|
||||
proto := ""
|
||||
for _, line := range lines {
|
||||
|
@ -178,9 +167,9 @@ func parseProtocols(input []byte) Parsed {
|
|||
return res
|
||||
}
|
||||
|
||||
func parseSymbols(input []byte) Parsed {
|
||||
func parseSymbols(reader io.Reader) Parsed {
|
||||
res := Parsed{}
|
||||
lines := getLines(input)
|
||||
lines := getNonEmptyLines(reader)
|
||||
|
||||
for _, line := range lines {
|
||||
if specialLine(line) {
|
||||
|
@ -196,9 +185,9 @@ func parseSymbols(input []byte) Parsed {
|
|||
return Parsed{"symbols": res}
|
||||
}
|
||||
|
||||
func parseRoutes(input []byte) Parsed {
|
||||
func parseRoutes(reader io.Reader) Parsed {
|
||||
res := Parsed{}
|
||||
lines := getLines(input)
|
||||
lines := getNonEmptyLines(reader)
|
||||
|
||||
routes := []Parsed{}
|
||||
route := Parsed{}
|
||||
|
@ -325,9 +314,9 @@ func parseRoutesLargeCommunities(groups []string, res Parsed) {
|
|||
res["large_communities"] = communities
|
||||
}
|
||||
|
||||
func parseRoutesCount(input []byte) Parsed {
|
||||
func parseRoutesCount(reader io.Reader) Parsed {
|
||||
res := Parsed{}
|
||||
lines := getLines(input)
|
||||
lines := getNonEmptyLines(reader)
|
||||
|
||||
for _, line := range lines {
|
||||
if specialLine(line) {
|
||||
|
@ -351,7 +340,7 @@ func isCorrectChannel(currentIPVersion string) bool {
|
|||
return currentIPVersion == IPVersion
|
||||
}
|
||||
|
||||
func parseBgp(input string) Parsed {
|
||||
func parseBgp(lines string) Parsed {
|
||||
res := Parsed{}
|
||||
routeChanges := Parsed{}
|
||||
|
||||
|
@ -366,9 +355,13 @@ func parseBgp(input string) Parsed {
|
|||
func(l string) bool { return parseBgpStringValuesRx(l, res) },
|
||||
}
|
||||
|
||||
lines := getLinesFromString(input)
|
||||
ipVersion := ""
|
||||
for _, line := range lines {
|
||||
|
||||
reader := strings.NewReader(lines)
|
||||
scanner := bufio.NewScanner(reader)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
if m := regex.bgp.channel.FindStringSubmatch(line); len(m) > 0 {
|
||||
ipVersion = m[1]
|
||||
}
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
package bird
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func readSampleData(filename string) ([]byte, error) {
|
||||
func openFile(filename string) (*os.File, error) {
|
||||
sample := "../test/" + filename
|
||||
return ioutil.ReadFile(sample)
|
||||
return os.Open(sample)
|
||||
}
|
||||
|
||||
func TestParseBgpRoutes(t *testing.T) {
|
||||
|
@ -42,12 +41,13 @@ func TestParseBgpRoutes(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestParseRoutesAll(t *testing.T) {
|
||||
sample, err := readSampleData("routes_bird1_ipv4.sample")
|
||||
f, err := openFile("routes_bird1_ipv4.sample")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
result := parseRoutes(sample)
|
||||
result := parseRoutes(f)
|
||||
routes, ok := result["routes"].([]Parsed)
|
||||
if !ok {
|
||||
t.Error("Error getting routes")
|
||||
|
@ -135,13 +135,14 @@ func TestParseRoutesAllBird2(t *testing.T) {
|
|||
runTestForIpv6WithTemplate("routes_bird2_ipv6.sample", t)
|
||||
}
|
||||
|
||||
func runTestForIpv6WithTemplate(template string, t *testing.T) {
|
||||
sample, err := readSampleData(template)
|
||||
func runTestForIpv6WithTemplate(file string, t *testing.T) {
|
||||
f, err := openFile(file)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
result := parseRoutes(sample)
|
||||
result := parseRoutes(f)
|
||||
routes, ok := result["routes"].([]Parsed)
|
||||
if !ok {
|
||||
t.Fatal("Error getting routes")
|
||||
|
@ -151,8 +152,6 @@ func runTestForIpv6WithTemplate(template string, t *testing.T) {
|
|||
t.Fatal("Expected 3 routes but got ", len(routes))
|
||||
}
|
||||
|
||||
fmt.Println(routes[1])
|
||||
|
||||
assertRouteIsEqual(expectedRoute{
|
||||
network: "2001:4860::/32",
|
||||
gateway: "fe80:ffff:ffff::1",
|
||||
|
|
Loading…
Add table
Reference in a new issue