From 424e38661227c9f31612379ac631bdeea83040a4 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Sun, 15 Feb 2015 13:19:08 -0800 Subject: [PATCH] Conf is now in its own thread and accessed thread safely via channels adding deployments now works like that conf now persists --- cmd/warrend/cmd_reg.go | 5 +- cmd/warrend/cmd_status.go | 5 +- cmd/warrend/conf.go | 29 ----------- cmd/warrend/conf/conf.go | 87 +++++++++++++++++++++++++++++++++ cmd/warrend/conf/deployments.go | 54 ++++++++++++++++++++ cmd/warrend/deployments.go | 31 ------------ cmd/warrend/main.go | 9 ++-- 7 files changed, 152 insertions(+), 68 deletions(-) delete mode 100644 cmd/warrend/conf.go create mode 100644 cmd/warrend/conf/conf.go create mode 100644 cmd/warrend/conf/deployments.go delete mode 100644 cmd/warrend/deployments.go diff --git a/cmd/warrend/cmd_reg.go b/cmd/warrend/cmd_reg.go index af9d5e0..196aeeb 100644 --- a/cmd/warrend/cmd_reg.go +++ b/cmd/warrend/cmd_reg.go @@ -1,6 +1,7 @@ package main import ( + "github.com/dballard/warren/cmd/warrend/conf" "github.com/dballard/warren/lib/warren" "net" "strings" @@ -28,7 +29,7 @@ func regRun(cmd *SockCommand, c net.Conn, args ...string) { } // get either supplied nick or parse from dir - d := new(Deployment) + d := new(conf.DeploymentMsg) d.Path = args[0] if len(args) >= 2 && strings.TrimSpace(args[1]) != "" { d.Name = args[1] @@ -40,7 +41,7 @@ func regRun(cmd *SockCommand, c net.Conn, args ...string) { d.Name = parts[len(parts)-1] } } - err := addDeployment(d) + err := conf.AddDeployment(d) if err != nil { warren.WriteStringz(c, "ERROR: "+err.Error()) return diff --git a/cmd/warrend/cmd_status.go b/cmd/warrend/cmd_status.go index be00229..40099ca 100644 --- a/cmd/warrend/cmd_status.go +++ b/cmd/warrend/cmd_status.go @@ -1,6 +1,7 @@ package main import ( + "github.com/dballard/warren/cmd/warrend/conf" "github.com/dballard/warren/lib/warren" "net" ) @@ -27,8 +28,8 @@ func statusRun(cmd *SockCommand, c net.Conn, args ...string) { warren.WriteStringz(c, "Status\n") - for _, d := range deployments { - warren.WriteStringz(c, d.Name+": "+d.Path) + for n, p := range conf.GetConf().Deployments { + warren.WriteStringz(c, n+": "+p) } } diff --git a/cmd/warrend/conf.go b/cmd/warrend/conf.go deleted file mode 100644 index 7ec7b74..0000000 --- a/cmd/warrend/conf.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "github.com/dballard/warren/lib/warren" - "os" -) - -type Conf struct { - deployments []string -} - -var conf *Conf = nil - -func LoadConf() { - file, err := os.Open(warren.WarrendConf) - if err != nil { - fmt.Println("Error loading ", warren.WarrendConf, ": ", err) - return - } - decoder := json.NewDecoder(file) - conf = new(Conf) - err = decoder.Decode(conf) - if err != nil { - conf = nil - fmt.Println("Error parsing ", warren.WarrendConf, ": ", err) - } -} diff --git a/cmd/warrend/conf/conf.go b/cmd/warrend/conf/conf.go new file mode 100644 index 0000000..bd99788 --- /dev/null +++ b/cmd/warrend/conf/conf.go @@ -0,0 +1,87 @@ +package conf + +import ( + "encoding/json" + "errors" + "fmt" + "github.com/dballard/warren/lib/warren" + "os" +) + +// Conf package - thread safe conf +// All write ops are public API functions +// that internall use channels to thread safely queue writes +// all write ops cause FS conf writes so that state is preserved +// Reads return copies of data + +type Conf struct { + // name : path + Deployments map[string]string +} + +var conf *Conf = nil +var Init = make(chan bool) + +var addDeploymentChan = make(chan DeploymentMsg) + +func loadConf() { + file, err := os.Open(warren.WarrendConf) + if err != nil { + fmt.Println("Error loading ", warren.WarrendConf, ": ", err) + return + } + defer file.Close() + decoder := json.NewDecoder(file) + conf = new(Conf) + err = decoder.Decode(conf) + if err != nil { + conf = nil + fmt.Println("Error parsing ", warren.WarrendConf, ": ", err) + } + if conf.Deployments == nil { + conf.Deployments = make(map[string]string) + } +} + +func saveConf() error { + file, err := os.Create(warren.WarrendConf) + if err != nil { + // TODO: Um, more than noting we might want to do something more drastic + return errors.New("Error: could not open conf file for saving: " + err.Error()) + } + defer file.Close() + jdata, err := json.MarshalIndent(conf, "", "\t") + if err != nil { + return errors.New("Error: Could not enocde to json: " + err.Error()) + } + + if _, err := file.Write(jdata); err != nil { + return errors.New("Error: Could not write to file: " + err.Error()) + } + + return nil +} + +func GetConf() Conf { + return *conf +} + +func Run() { + loadConf() + if conf == nil { + fmt.Println("failed to load conf") + Init <- false + } + + // set up comm chans + + Init <- true + // loop for Writes + for { + select { + case dm := <-addDeploymentChan: + addDeployment(&dm) + } + } + +} diff --git a/cmd/warrend/conf/deployments.go b/cmd/warrend/conf/deployments.go new file mode 100644 index 0000000..7c8f138 --- /dev/null +++ b/cmd/warrend/conf/deployments.go @@ -0,0 +1,54 @@ +package conf + +import ( + "errors" + "os" +) + +type DeploymentMsg struct { + Name string + Path string + Reply chan error +} + +// Validate a deployment is ok to insert +// internal thread unsafe +func validateDeployment(d *DeploymentMsg) error { + // check if exists + if _, ok := conf.Deployments[d.Name]; ok { + return errors.New("Deployment with that name already exists") + } + + // check if dir exists + if _, err := os.Stat(d.Path); err != nil { + return err + } + return nil +} + +// given a valid deployment, add it +// internal, thread unsafe +func addDeployment(d *DeploymentMsg) error { + if err := validateDeployment(d); err != nil { + d.Reply <- err + return err + } + conf.Deployments[d.Name] = d.Path + saveConf() + d.Reply <- nil + return nil +} + +// conf API interface to add a deployment, vets it +func AddDeployment(d *DeploymentMsg) error { + + d.Reply = make(chan error) + // add to conf / save + addDeploymentChan <- *d + err := <-d.Reply + return err + + // TODO: register with runner, like conf would + + return nil +} diff --git a/cmd/warrend/deployments.go b/cmd/warrend/deployments.go deleted file mode 100644 index afae33b..0000000 --- a/cmd/warrend/deployments.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "errors" - "os" -) - -type Deployment struct { - Name string - Path string -} - -var deployments map[string]*Deployment = make(map[string]*Deployment) - -func addDeployment(d *Deployment) error { - // check if exists - if _, ok := deployments[d.Name]; ok { - return errors.New("Deployment with that name already exists") - } - - // check if dir exists - if _, err := os.Stat(d.Path); err != nil { - return err - } - // add to conf / save - deployments[d.Name] = d - - // TODO: register with runner, like conf would - - return nil -} diff --git a/cmd/warrend/main.go b/cmd/warrend/main.go index 83cb827..3572212 100644 --- a/cmd/warrend/main.go +++ b/cmd/warrend/main.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "github.com/dballard/warren/cmd/warrend/conf" "github.com/dballard/warren/lib/warren" "log" "net" @@ -113,9 +114,9 @@ func main() { log.Fatal("warrend instance already running") } - LoadConf() - if conf == nil { - log.Fatal("failed to load conf") + go conf.Run() + if cinit := <-conf.Init; !cinit { + return } initRunning() @@ -132,7 +133,7 @@ func main() { syscall.SIGHUP, ) go func() { - _ = <-c + <-c Shutdown() }()