1
0
Fork 0
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:
Daniel Czerwonk 2018-01-18 00:44:22 +01:00
parent 68ce3c8422
commit f905c9c3de
3 changed files with 47 additions and 47 deletions

View file

@ -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
}

View file

@ -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]
}

View file

@ -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",