Started implementing the graph

This commit is contained in:
Julian Kornberger 2016-03-07 02:29:31 +01:00
parent c63fd27867
commit 1fd59e6156
3 changed files with 116 additions and 12 deletions

View File

@ -23,7 +23,7 @@ var (
wsserverForNodes *websocketserver.Server wsserverForNodes *websocketserver.Server
respondDaemon *respond.Daemon respondDaemon *respond.Daemon
nodes = models.NewNodes() nodes = models.NewNodes()
aliases = models.NewNodes() //aliases = models.NewNodes()
) )
func main() { func main() {
@ -35,10 +35,11 @@ func main() {
saveInterval := time.Second * time.Duration(config.Nodes.SaveInterval) saveInterval := time.Second * time.Duration(config.Nodes.SaveInterval)
if config.Nodes.Enable { if config.Nodes.Enable {
go nodes.Saver(config.Nodes.NodesPath, saveInterval) go nodes.Saver(config.Nodes.NodesPath, config.Nodes.GraphsPath, saveInterval)
} }
if config.Nodes.AliasesEnable { if config.Nodes.AliasesEnable {
go aliases.Saver(config.Nodes.AliasesPath, saveInterval) // FIXME what does this do?
//go aliases.Saver(config.Nodes.AliasesPath, saveInterval)
} }
if config.Webserver.Enable { if config.Webserver.Enable {

103
models/graph.go Normal file
View File

@ -0,0 +1,103 @@
package models
import (
"fmt"
"strings"
)
type Graph struct {
Version int `json:"version"`
Batadv struct {
Links []*GraphLink `json:"links"`
} `json:"batadv"`
}
type GraphLink struct {
Source string `json:"source"`
Target string `json:"target"`
VPN bool `json:"vpn"`
TQ float32 `json:"tq"`
Bidirect bool `json:"bidirect"`
}
type GraphBuilder struct {
macToID map[string]string // mapping from MAC address to node id
links map[string]*GraphLink // mapping from $idA-$idB to existing link
}
func (nodes *Nodes) BuildGraph() *Graph {
builder := &GraphBuilder{
macToID: make(map[string]string),
links: make(map[string]*GraphLink),
}
builder.readNodes(nodes.List)
graph := &Graph{Version: 2}
graph.Batadv.Links = builder.Links()
return graph
}
func (builder *GraphBuilder) readNodes(nodes map[string]*Node) {
// Fill mac->id map
for sourceId, node := range nodes {
if neighbours := node.Neighbours; neighbours != nil {
for sourceAddress, _ := range neighbours.Batadv {
builder.macToID[sourceAddress] = sourceId
}
}
}
// Add links
for sourceId, node := range nodes {
if neighbours := node.Neighbours; neighbours != nil {
for _, batadvNeighbours := range neighbours.Batadv {
for targetAddress, link := range batadvNeighbours.Neighbours {
if targetId, found := builder.macToID[targetAddress]; found {
builder.addLink(targetId, sourceId, link.Tq)
}
}
}
}
}
}
func (builder *GraphBuilder) Links() []*GraphLink {
i := 0
links := make([]*GraphLink, len(builder.links))
for _, link := range builder.links {
links[i] = link
i += 1
}
return links
}
func (builder *GraphBuilder) addLink(targetId string, sourceId string, linkTq int) {
// Order IDs to get generate the key
var key string
if strings.Compare(sourceId, targetId) > 0 {
key = fmt.Sprintf("%s-%s", sourceId, targetId)
} else {
key = fmt.Sprintf("%s-%s", targetId, sourceId)
}
var tq float32
if linkTq > 0 {
tq = float32(1.0 / (float32(linkTq) / 255.0))
}
if link, ok := builder.links[key]; !ok {
builder.links[key] = &GraphLink{
Source: sourceId,
Target: targetId,
TQ: tq,
}
} else {
// Use lowest of both link qualities
if tq < link.TQ {
link.TQ = tq
}
link.Bidirect = true
}
}

View File

@ -62,25 +62,25 @@ func (nodes *Nodes) Get(nodeID string) *Node {
} }
// Saves the cached DB to json file periodically // Saves the cached DB to json file periodically
func (nodes *Nodes) Saver(outputFile string, saveInterval time.Duration) { func (nodes *Nodes) Saver(nodesPath string, graphPath string, saveInterval time.Duration) {
c := time.Tick(saveInterval) c := time.Tick(saveInterval)
for range c { for range c {
nodes.save(outputFile) log.Println("saving", len(nodes.List), "nodes")
}
}
func (nodes *Nodes) save(outputFile string) {
nodes.Timestamp = time.Now() nodes.Timestamp = time.Now()
nodes.Lock() nodes.Lock()
data, err := json.Marshal(nodes) save(nodes, nodesPath)
save(nodes.BuildGraph(), graphPath)
nodes.Unlock() nodes.Unlock()
}
}
func save(input interface{}, outputFile string) {
data, err := json.Marshal(input)
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)
} }
log.Println("saving", len(nodes.List), "nodes")
tmpFile := outputFile + ".tmp" tmpFile := outputFile + ".tmp"