changed server to use channels instead of cond for wakeup, removed config hashing, added config path to config struct

This commit is contained in:
Christopher Ramey 2021-02-14 09:26:56 -09:00
parent d5389caadb
commit 4c16211e89
7 changed files with 98 additions and 73 deletions

View File

@ -10,13 +10,16 @@ type Config struct {
Groups map[string]*Group Groups map[string]*Group
Alarms map[string]alarm.Alarm Alarms map[string]alarm.Alarm
Interval time.Duration Interval time.Duration
Hash string Listen string
Path string
} }
func NewConfig() *Config { func NewConfig() *Config {
return &Config{ return &Config{
// Default check interval, 30 seconds // Default check interval, 30 seconds
Interval: time.Second * 30, Interval: time.Second * 30,
// Default listen address
Listen: "127.0.0.1:8282",
} }
} }

View File

@ -1,7 +1,6 @@
package config package config
import ( import (
"encoding/hex"
"fmt" "fmt"
"git.binarythought.com/cdramey/alrm/alarm" "git.binarythought.com/cdramey/alrm/alarm"
"git.binarythought.com/cdramey/alrm/check" "git.binarythought.com/cdramey/alrm/check"
@ -30,6 +29,7 @@ type Parser struct {
func (p *Parser) Parse(fn string) (*Config, error) { func (p *Parser) Parse(fn string) (*Config, error) {
config := NewConfig() config := NewConfig()
config.Path = fn
tok, err := NewTokenizer(fn) tok, err := NewTokenizer(fn)
if err != nil { if err != nil {
return nil, err return nil, err
@ -70,6 +70,8 @@ func (p *Parser) Parse(fn string) (*Config, error) {
fn, tok.Line(), value, fn, tok.Line(), value,
) )
} }
case "listen":
config.Listen = value
default: default:
return nil, fmt.Errorf("unknown key for set in %s, line %d: \"%s\"", return nil, fmt.Errorf("unknown key for set in %s, line %d: \"%s\"",
fn, tok.Line(), tk, fn, tok.Line(), tk,
@ -200,7 +202,6 @@ func (p *Parser) Parse(fn string) (*Config, error) {
if err := tok.Err(); err != nil { if err := tok.Err(); err != nil {
return nil, err return nil, err
} }
config.Hash = hex.EncodeToString(tok.Hash.Sum(nil))
return config, nil return config, nil
} }

View File

@ -2,9 +2,7 @@ package config
import ( import (
"bufio" "bufio"
"crypto/sha256"
"fmt" "fmt"
"hash"
"io" "io"
"os" "os"
"strings" "strings"
@ -19,7 +17,6 @@ const (
) )
type Tokenizer struct { type Tokenizer struct {
Hash hash.Hash
curline int curline int
repline int repline int
file *os.File file *os.File
@ -36,7 +33,6 @@ func NewTokenizer(fn string) (*Tokenizer, error) {
return nil, err return nil, err
} }
tk.Hash = sha256.New()
tk.reader = bufio.NewReader(tk.file) tk.reader = bufio.NewReader(tk.file)
return tk, nil return tk, nil
} }
@ -62,7 +58,6 @@ func (t *Tokenizer) Scan() bool {
t.err = fmt.Errorf("invalid utf-8 encoding on line %s", t.repline) t.err = fmt.Errorf("invalid utf-8 encoding on line %s", t.repline)
break break
} }
t.Hash.Write([]byte(string(r)))
switch state { switch state {
case TK_NONE: case TK_NONE:

26
main.go
View File

@ -5,26 +5,27 @@ import (
"flag" "flag"
"fmt" "fmt"
"git.binarythought.com/cdramey/alrm/config" "git.binarythought.com/cdramey/alrm/config"
"git.binarythought.com/cdramey/alrm/server"
"os" "os"
"strings" "strings"
) )
func main() { func main() {
cfgPath := flag.String("c", "", "path to configuration file") cfgpath := flag.String("c", "", "path to configuration file")
debuglvl := flag.Int("d", 0, "debug level") debuglvl := flag.Int("d", 0, "debug level")
flag.Usage = printUsage flag.Usage = printUsage
flag.Parse() flag.Parse()
if *cfgPath == "" { if *cfgpath == "" {
searchpaths := []string{"/etc/alrmrc", "./alrmrc"} searchpaths := []string{"/etc/alrmrc", "./alrmrc"}
for _, sp := range searchpaths { for _, sp := range searchpaths {
if _, err := os.Stat(sp); err == nil { if _, err := os.Stat(sp); err == nil {
*cfgPath = sp *cfgpath = sp
break break
} }
} }
if *cfgPath == "" { if *cfgpath == "" {
fmt.Fprintf(os.Stderr, "cannot find configuration\n") fmt.Fprintf(os.Stderr, "cannot find configuration\n")
os.Exit(1) os.Exit(1)
} }
@ -34,10 +35,10 @@ func main() {
switch command { switch command {
case "config": case "config":
if *debuglvl > 0 { if *debuglvl > 0 {
fmt.Printf("checking config %s .. \n", *cfgPath) fmt.Printf("checking config %s .. \n", *cfgpath)
} }
cfg, err := config.ReadConfig(*cfgPath, *debuglvl) cfg, err := config.ReadConfig(*cfgpath, *debuglvl)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err.Error()) fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1) os.Exit(1)
@ -61,7 +62,7 @@ func main() {
os.Exit(1) os.Exit(1)
} }
cfg, err := config.ReadConfig(*cfgPath, 0) cfg, err := config.ReadConfig(*cfgpath, 0)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err.Error()) fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1) os.Exit(1)
@ -90,7 +91,7 @@ func main() {
os.Exit(1) os.Exit(1)
} }
cfg, err := config.ReadConfig(*cfgPath, 0) cfg, err := config.ReadConfig(*cfgpath, 0)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err.Error()) fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1) os.Exit(1)
@ -110,17 +111,14 @@ func main() {
fmt.Printf("check successful\n") fmt.Printf("check successful\n")
case "server": case "server":
cfg, err := config.ReadConfig(*cfgPath, *debuglvl) cfg, err := config.ReadConfig(*cfgpath, *debuglvl)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err.Error()) fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1) os.Exit(1)
} }
err = startServer(cfg, *debuglvl) srv := server.NewServer(cfg, *debuglvl)
if err != nil { srv.Start()
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
}
case "help", "": case "help", "":
printUsage() printUsage()

View File

@ -1,51 +0,0 @@
package main
import (
"fmt"
"git.binarythought.com/cdramey/alrm/config"
"sync"
"time"
)
func startServer(cfg *config.Config, debuglvl int) error {
c := sync.NewCond(&sync.Mutex{})
for _, g := range cfg.Groups {
go worker(g, c, debuglvl)
}
t := time.NewTicker(cfg.Interval)
defer t.Stop()
for {
select {
case r := <-t.C:
if debuglvl > 0 {
fmt.Printf("Interval check at %s\n", r)
}
c.Broadcast()
}
}
return nil
}
func worker(g *config.Group, c *sync.Cond, debuglvl int) {
for {
if debuglvl > 2 {
fmt.Printf("%s goroutine waiting.. \n", g.Name)
}
c.L.Lock()
c.Wait()
c.L.Unlock()
if debuglvl > 2 {
fmt.Printf("%s goroutine wake.. \n", g.Name)
}
for _, h := range g.Hosts {
for _, c := range h.Checks {
err := c.Check(debuglvl)
if err != nil {
fmt.Printf("Check error: %s\n", err)
}
}
}
}
}

47
server/server.go Normal file
View File

@ -0,0 +1,47 @@
package server
import (
"fmt"
"git.binarythought.com/cdramey/alrm/config"
"time"
)
type Server struct {
workers []*worker
cfg *config.Config
debuglvl int
httpsrv http.Server
}
func (srv *Server) Start() {
for _, w := range srv.workers {
go w.start(srv.debuglvl)
}
t := time.NewTicker(srv.cfg.Interval)
defer t.Stop()
for {
select {
case r := <-t.C:
if srv.debuglvl > 0 {
fmt.Printf("interval check at %s\n", r)
}
for _, w := range srv.workers {
select {
case w.wake <- true:
default:
}
}
}
}
}
func NewServer(cfg *config.Config, debuglvl int) *Server {
srv := &Server{cfg: cfg, debuglvl: debuglvl}
for _, g := range cfg.Groups {
w := &worker{group: g, wake: make(chan bool)}
srv.workers = append(srv.workers, w)
}
return srv
}

32
server/worker.go Normal file
View File

@ -0,0 +1,32 @@
package server
import (
"fmt"
"git.binarythought.com/cdramey/alrm/config"
)
type worker struct {
wake chan bool
group *config.Group
}
func (w *worker) start(debuglvl int) {
for {
if debuglvl > 2 {
fmt.Printf("%s worker waiting.. \n", w.group.Name)
}
<-w.wake
if debuglvl > 2 {
fmt.Printf("%s worker wake.. \n", w.group.Name)
}
for _, h := range w.group.Hosts {
for _, c := range h.Checks {
err := c.Check(debuglvl)
if err != nil {
fmt.Printf("check error: %s\n", err)
}
}
}
}
}