Conf is now in its own thread and accessed thread safely via channels

adding deployments now works like that
conf now persists
This commit is contained in:
Dan Ballard 2015-02-15 13:19:08 -08:00
parent 02b3ebf87b
commit 424e386612
7 changed files with 152 additions and 68 deletions

View File

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

View File

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

View File

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

87
cmd/warrend/conf/conf.go Normal file
View File

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

View File

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

View File

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

View File

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