From d61ab0638fb29591e0aaa3125757332320d5b43d Mon Sep 17 00:00:00 2001 From: Blallo Date: Wed, 5 Dec 2018 09:18:40 +0100 Subject: [PATCH 1/7] sigusr2 triggering buffer cleanup also via ctrlsock --- cmd/circologd/main.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cmd/circologd/main.go b/cmd/circologd/main.go index b40641c..4d73150 100644 --- a/cmd/circologd/main.go +++ b/cmd/circologd/main.go @@ -32,7 +32,7 @@ func main() { flag.Parse() interrupt := make(chan os.Signal, 1) - signal.Notify(interrupt, syscall.SIGINT, syscall.SIGUSR1, syscall.SIGTERM) + signal.Notify(interrupt, syscall.SIGINT, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGTERM) hub := circolog.NewHub(*bufsize) handler := syslog.NewChannelHandler(hub.LogMessages) @@ -115,6 +115,15 @@ func main() { log.Println("paused") } } + if sig == syscall.SIGUSR2 { + hub.Commands <- circolog.HubFullCommand{Command: circolog.CommandClear} + resp := <-hub.Responses + if resp.Value.(bool) { + log.Println("buffer cleaned") + } else { + log.Println("buffer NOT cleaned") + } + } if sig == syscall.SIGTERM || sig == syscall.SIGINT { log.Println("Quitting because of signal", sig) server.Kill() From dfe1e60146f1f7f33829b755fa19cf75165c20fd Mon Sep 17 00:00:00 2001 From: Blallo Date: Wed, 19 Dec 2018 17:30:04 +0100 Subject: [PATCH 2/7] Typo in comment --- hub.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hub.go b/hub.go index 639612f..be530e4 100644 --- a/hub.go +++ b/hub.go @@ -135,7 +135,7 @@ func (h *Hub) Run() { } } -// Clear removes every all elements from the buffer +// Clear removes all elements from the buffer func (h *Hub) clear() { buf := h.circbuf for i := 0; i < buf.Len(); i++ { From 0747959f8a6fe30a1e31a8964388910080dbb520 Mon Sep 17 00:00:00 2001 From: Blallo Date: Thu, 20 Dec 2018 09:45:05 +0100 Subject: [PATCH 3/7] First draft of control command --- cmd/circologctl/main.go | 90 +++++++++++++++++++++++++++++++++++++++ cmd/circologd/http_ctl.go | 58 ++++++++++++++++++++++--- cmd/circologd/main.go | 3 +- 3 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 cmd/circologctl/main.go diff --git a/cmd/circologctl/main.go b/cmd/circologctl/main.go new file mode 100644 index 0000000..ea87c38 --- /dev/null +++ b/cmd/circologctl/main.go @@ -0,0 +1,90 @@ +package main + +import ( + "flag" + "fmt" + "io" + "os" +) + +var globalOpts struct { + ctlSock string + verbose bool +} + +type commandFunc func([]string) error + +var cmdMap map[string]commandFunc + +func init() { + cmdMap = map[string]commandFunc{ + // TODO: implement set and get of config at runtime + //"set": setCmd, + //"get": getCmd, + "pause": pauseCmd, + "reload": reloadCmd, + "restart": restartCmd, + "help": helpCmd, + } +} + +//func setCmd(ctlSock string, args []string) error {} + +//func getCmd(ctlSock string, args []string) error {} + +func pauseCmd(args []string) error { + return nil +} + +func reloadCmd(args []string) error { + return nil +} + +func restartCmd(args []string) error { + return nil +} + +func helpCmd(args []string) error { + usage(os.Stdout) + os.Exit(0) + return nil +} + +func usage(w io.Writer) { + fmt.Fprintf(w, "USAGE: %s [globalOpts] [SUBCOMMAND] [opts]\n", os.Args[0]) + fmt.Fprintf(w, "\nSUBCOMMANDS:\n\n") + for command := range cmdMap { + fmt.Fprintf(w, "\t%s\n", command) + } +} + +func parseAndRun(args []string) { + cmdName := args[0] + cmdToRun, ok := cmdMap[cmdName] + if !ok { + fmt.Fprintf(os.Stderr, "Unknown subcommand: %s\n", cmdName) + usage(os.Stderr) + os.Exit(2) + } + err := cmdToRun(args) + if err != nil { + fmt.Fprintf(os.Stderr, "Error:\n%s\n", err) + os.Exit(1) + } +} + +func main() { + flag.StringVar(&globalOpts.ctlSock, "ctl-socket", "/tmp/circologd-ctl.sock", + "Path to a unix domain socket for the control server; leave empty to disable") + flag.BoolVar(&globalOpts.verbose, "verbose", false, "Print more output") + flag.Parse() + args := flag.Args() + if globalOpts.verbose { + fmt.Fprintf(os.Stdout, "Args: %v", args) + } + if len(args) == 0 { + usage(os.Stderr) + os.Exit(-1) + } + parseAndRun(args) +} diff --git a/cmd/circologd/http_ctl.go b/cmd/circologd/http_ctl.go index cde8538..f35a0bc 100644 --- a/cmd/circologd/http_ctl.go +++ b/cmd/circologd/http_ctl.go @@ -2,21 +2,30 @@ package main import ( "encoding/json" + "fmt" + "log" "net/http" + "os" + fractal "git.lattuga.net/blallo/gotools/formatting" "git.lattuga.net/boyska/circolog" "github.com/gorilla/mux" ) -func setupHTTPCtl(hub circolog.Hub) *mux.Router { - mux := mux.NewRouter() - mux.HandleFunc("/pause/toggle", togglePause(hub)).Methods("POST") - mux.HandleFunc("/logs/clear", clearQueue(hub)).Methods("POST") - return mux +func setupHTTPCtl(hub circolog.Hub, verbose bool) *mux.Router { + m := mux.NewRouter() + m.HandleFunc("/pause/toggle", togglePause(hub, verbose)).Methods("POST") + m.HandleFunc("/logs/clear", clearQueue(hub, verbose)).Methods("POST") + m.HandleFunc("/help", printHelp(verbose)).Methods("GET") + m.HandleFunc("/echo", echo(verbose)).Methods("GET") + return m } -func togglePause(hub circolog.Hub) http.HandlerFunc { +func togglePause(hub circolog.Hub, verbose bool) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + if verbose { + log.Printf("[%s] %s - toggled pause", r.Method, r.RemoteAddr) + } hub.Commands <- circolog.HubFullCommand{Command: circolog.CommandPauseToggle} resp := <-hub.Responses active := resp.Value.(bool) @@ -26,8 +35,11 @@ func togglePause(hub circolog.Hub) http.HandlerFunc { } } -func clearQueue(hub circolog.Hub) http.HandlerFunc { +func clearQueue(hub circolog.Hub, verbose bool) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + if verbose { + log.Printf("[%s] %s - cleared queue", r.Method, r.RemoteAddr) + } hub.Commands <- circolog.HubFullCommand{Command: circolog.CommandClear} resp := <-hub.Responses success := resp.Value.(bool) @@ -36,3 +48,35 @@ func clearQueue(hub circolog.Hub) http.HandlerFunc { enc.Encode(map[string]interface{}{"success": success}) } } + +func printHelp(verbose bool) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if verbose { + log.Printf("[%s] %s - asked for help", r.Method, r.RemoteAddr) + } + w.Header().Set("content-type", "application/json") + enc := json.NewEncoder(w) + var pathsWithDocs = map[string]string{ + "/pause/toggle": "Toggle the server from pause state (not listening)", + "/logs/clear": "Wipe the buffer from all the messages", + "/help": "This help", + "/echo": "Answers to heartbeat", + } + fractal.EncodeJSON(pathsWithDocs, enc) + if verbose { + errEnc := json.NewEncoder(os.Stderr) + fractal.EncodeJSON(pathsWithDocs, errEnc) + } + } +} + +func echo(verbose bool) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + log.Println("Echo") + if verbose { + log.Printf("[%s] %s - asked for echo", r.Method, r.RemoteAddr) + } + w.Header().Set("content-type", "text/plain") + fmt.Fprintln(w, "I am on!") + } +} diff --git a/cmd/circologd/main.go b/cmd/circologd/main.go index 4d73150..6f269c7 100644 --- a/cmd/circologd/main.go +++ b/cmd/circologd/main.go @@ -29,6 +29,7 @@ func main() { queryAddr := flag.String("query-addr", "127.0.0.1:9080", "Address:port where to bind the query service") querySocket := flag.String("query-socket", "", "Path to a unix domain socket for the HTTP server; recommended for security reasons!") ctlSocket := flag.String("ctl-socket", "/tmp/circologd-ctl.sock", "Path to a unix domain socket for the control server; leave empty to disable") + verbose := flag.Bool("verbose", false, "Print more output executing the daemon") flag.Parse() interrupt := make(chan os.Signal, 1) @@ -85,7 +86,7 @@ func main() { }() } - httpCtlServer := http.Server{Handler: setupHTTPCtl(hub)} + httpCtlServer := http.Server{Handler: setupHTTPCtl(hub, *verbose)} if *ctlSocket != "" { fmt.Printf("Binding address `%s` [http]\n", *ctlSocket) unixListener, err := net.Listen("unix", *ctlSocket) From 9ef425d827404b1673d71afad08d1a9e429869ce Mon Sep 17 00:00:00 2001 From: Blallo Date: Fri, 21 Dec 2018 18:09:32 +0100 Subject: [PATCH 4/7] [ctl] pause subcommand partially implemented --- cmd/circologctl/main.go | 79 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 4 deletions(-) diff --git a/cmd/circologctl/main.go b/cmd/circologctl/main.go index ea87c38..4f2ff51 100644 --- a/cmd/circologctl/main.go +++ b/cmd/circologctl/main.go @@ -1,10 +1,16 @@ package main import ( + "context" "flag" "fmt" "io" + "io/ioutil" + "net" + "net/http" "os" + "strconv" + "strings" ) var globalOpts struct { @@ -12,6 +18,8 @@ var globalOpts struct { verbose bool } +var ctl http.Client + type commandFunc func([]string) error var cmdMap map[string]commandFunc @@ -32,8 +40,66 @@ func init() { //func getCmd(ctlSock string, args []string) error {} +func parsePauseOpts(postponeTime string) (string, error) { + var waitTime int64 + var err error + L := len(postponeTime) + switch unit := postponeTime[L-1]; string(unit) { + case "s": + waitTime, err = strconv.ParseInt(postponeTime[:L-2], 10, 16) + if err != nil { + return "", err + } + case "m": + waitTime, err = strconv.ParseInt(postponeTime[:L-2], 10, 16) + if err != nil { + return "", err + } + waitTime = waitTime * 60 + case "h": + waitTime, err = strconv.ParseInt(postponeTime[:L-2], 10, 16) + if err != nil { + return "", err + } + waitTime = waitTime * 60 * 60 + case "d": + waitTime, err = strconv.ParseInt(postponeTime[:L-2], 10, 16) + if err != nil { + return "", err + } + waitTime = waitTime * 60 * 60 * 24 + case "w": + waitTime, err = strconv.ParseInt(postponeTime[:L-2], 10, 16) + if err != nil { + return "", err + } + waitTime = waitTime * 60 * 60 * 24 * 7 + } + return string(waitTime), nil +} + func pauseCmd(args []string) error { - return nil + var postBody string + var err error + flagset := flag.NewFlagSet(args[0], flag.ExitOnError) + postponeTime := flagset.String("postpone", "", "How long to wait before untoggling the state") + flagset.Parse(args[1:]) + if *postponeTime != "" { + postBody, err = parsePauseOpts(*postponeTime) + if err != nil { + return err + } + } + resp, err := ctl.Post("http://unix/pause/toggle", "application/octet-stream", strings.NewReader(postBody)) + if globalOpts.verbose { + defer resp.Body.Close() + bodyBytes, err2 := ioutil.ReadAll(resp.Body) + if err2 != nil { + return err2 + } + fmt.Println(string(bodyBytes)) + } + return err } func reloadCmd(args []string) error { @@ -66,6 +132,14 @@ func parseAndRun(args []string) { usage(os.Stderr) os.Exit(2) } + // from here: https://gist.github.com/teknoraver/5ffacb8757330715bcbcc90e6d46ac74 + ctl = http.Client{ + Transport: &http.Transport{ + DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { + return net.Dial("unix", globalOpts.ctlSock) + }, + }, + } err := cmdToRun(args) if err != nil { fmt.Fprintf(os.Stderr, "Error:\n%s\n", err) @@ -79,9 +153,6 @@ func main() { flag.BoolVar(&globalOpts.verbose, "verbose", false, "Print more output") flag.Parse() args := flag.Args() - if globalOpts.verbose { - fmt.Fprintf(os.Stdout, "Args: %v", args) - } if len(args) == 0 { usage(os.Stderr) os.Exit(-1) From 8865335515bde72d08006b67a47130a66bdd616f Mon Sep 17 00:00:00 2001 From: Blallo Date: Mon, 24 Dec 2018 15:54:22 +0100 Subject: [PATCH 5/7] answer to the right command --- cmd/circologd/http_ctl.go | 10 ++++++---- cmd/circologd/main.go | 10 ++++++---- hub.go | 9 ++++----- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/cmd/circologd/http_ctl.go b/cmd/circologd/http_ctl.go index f35a0bc..75a6223 100644 --- a/cmd/circologd/http_ctl.go +++ b/cmd/circologd/http_ctl.go @@ -26,8 +26,9 @@ func togglePause(hub circolog.Hub, verbose bool) http.HandlerFunc { if verbose { log.Printf("[%s] %s - toggled pause", r.Method, r.RemoteAddr) } - hub.Commands <- circolog.HubFullCommand{Command: circolog.CommandPauseToggle} - resp := <-hub.Responses + response := make(chan circolog.CommandResponse) + hub.Commands <- circolog.HubFullCommand{Command: circolog.CommandPauseToggle, Response: response} + resp := <-response active := resp.Value.(bool) w.Header().Set("content-type", "application/json") enc := json.NewEncoder(w) @@ -40,8 +41,9 @@ func clearQueue(hub circolog.Hub, verbose bool) http.HandlerFunc { if verbose { log.Printf("[%s] %s - cleared queue", r.Method, r.RemoteAddr) } - hub.Commands <- circolog.HubFullCommand{Command: circolog.CommandClear} - resp := <-hub.Responses + response := make(chan circolog.CommandResponse) + hub.Commands <- circolog.HubFullCommand{Command: circolog.CommandClear, Response: response} + resp := <-response success := resp.Value.(bool) w.Header().Set("content-type", "application/json") enc := json.NewEncoder(w) diff --git a/cmd/circologd/main.go b/cmd/circologd/main.go index 6f269c7..09e11cc 100644 --- a/cmd/circologd/main.go +++ b/cmd/circologd/main.go @@ -108,8 +108,9 @@ func main() { select { case sig := <-interrupt: if sig == syscall.SIGUSR1 { - hub.Commands <- circolog.HubFullCommand{Command: circolog.CommandPauseToggle} - resp := <-hub.Responses + response := make(chan circolog.CommandResponse) + hub.Commands <- circolog.HubFullCommand{Command: circolog.CommandPauseToggle, Response: response} + resp := <-response if resp.Value.(bool) { log.Println("resumed") } else { @@ -117,8 +118,9 @@ func main() { } } if sig == syscall.SIGUSR2 { - hub.Commands <- circolog.HubFullCommand{Command: circolog.CommandClear} - resp := <-hub.Responses + response := make(chan circolog.CommandResponse) + hub.Commands <- circolog.HubFullCommand{Command: circolog.CommandClear, Response: response} + resp := <-response if resp.Value.(bool) { log.Println("buffer cleaned") } else { diff --git a/hub.go b/hub.go index be530e4..61e2a91 100644 --- a/hub.go +++ b/hub.go @@ -35,7 +35,8 @@ const ( // An HubFullCommand is a Command, complete with arguments type HubFullCommand struct { - Command HubCommand + Command HubCommand + Response chan CommandResponse } type CommandResponse struct { Value interface{} @@ -46,7 +47,6 @@ type Hub struct { Unregister chan Client LogMessages chan format.LogParts Commands chan HubFullCommand - Responses chan CommandResponse clients map[Client]bool circbuf *ring.Ring @@ -59,7 +59,6 @@ func NewHub(ringBufSize int) Hub { Unregister: make(chan Client), LogMessages: make(chan format.LogParts), Commands: make(chan HubFullCommand), - Responses: make(chan CommandResponse), circbuf: ring.New(ringBufSize), } } @@ -125,11 +124,11 @@ func (h *Hub) Run() { case cmd := <-h.Commands: if cmd.Command == CommandClear { h.clear() - h.Responses <- CommandResponse{Value: true} + cmd.Response <- CommandResponse{Value: true} } if cmd.Command == CommandPauseToggle { active = !active - h.Responses <- CommandResponse{Value: active} + cmd.Response <- CommandResponse{Value: active} } } } From ce7e715c2f5fd6f52a4b796cd2f10f780eb81281 Mon Sep 17 00:00:00 2001 From: Blallo Date: Mon, 24 Dec 2018 16:48:11 +0100 Subject: [PATCH 6/7] use time.Duration for server autotoggle wait time --- cmd/circologctl/main.go | 57 ++++++----------------------------------- 1 file changed, 8 insertions(+), 49 deletions(-) diff --git a/cmd/circologctl/main.go b/cmd/circologctl/main.go index 4f2ff51..d95ffe0 100644 --- a/cmd/circologctl/main.go +++ b/cmd/circologctl/main.go @@ -9,8 +9,8 @@ import ( "net" "net/http" "os" - "strconv" "strings" + "time" ) var globalOpts struct { @@ -40,62 +40,21 @@ func init() { //func getCmd(ctlSock string, args []string) error {} -func parsePauseOpts(postponeTime string) (string, error) { - var waitTime int64 - var err error - L := len(postponeTime) - switch unit := postponeTime[L-1]; string(unit) { - case "s": - waitTime, err = strconv.ParseInt(postponeTime[:L-2], 10, 16) - if err != nil { - return "", err - } - case "m": - waitTime, err = strconv.ParseInt(postponeTime[:L-2], 10, 16) - if err != nil { - return "", err - } - waitTime = waitTime * 60 - case "h": - waitTime, err = strconv.ParseInt(postponeTime[:L-2], 10, 16) - if err != nil { - return "", err - } - waitTime = waitTime * 60 * 60 - case "d": - waitTime, err = strconv.ParseInt(postponeTime[:L-2], 10, 16) - if err != nil { - return "", err - } - waitTime = waitTime * 60 * 60 * 24 - case "w": - waitTime, err = strconv.ParseInt(postponeTime[:L-2], 10, 16) - if err != nil { - return "", err - } - waitTime = waitTime * 60 * 60 * 24 * 7 - } - return string(waitTime), nil -} - func pauseCmd(args []string) error { var postBody string - var err error + var dontChangeAgain time.Duration flagset := flag.NewFlagSet(args[0], flag.ExitOnError) - postponeTime := flagset.String("postpone", "", "How long to wait before untoggling the state") + waitTime := flagset.Duration("wait-time", dontChangeAgain, "How long to wait before untoggling the state, defaults to never") flagset.Parse(args[1:]) - if *postponeTime != "" { - postBody, err = parsePauseOpts(*postponeTime) - if err != nil { - return err - } + if *waitTime != dontChangeAgain { + postBody = fmt.Sprintf("waittime=%s", *waitTime) } resp, err := ctl.Post("http://unix/pause/toggle", "application/octet-stream", strings.NewReader(postBody)) if globalOpts.verbose { defer resp.Body.Close() - bodyBytes, err2 := ioutil.ReadAll(resp.Body) - if err2 != nil { - return err2 + bodyBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err } fmt.Println(string(bodyBytes)) } From a2303c1e1d971782e93d3f26190f15f719e1a894 Mon Sep 17 00:00:00 2001 From: Blallo Date: Mon, 24 Dec 2018 18:41:06 +0100 Subject: [PATCH 7/7] Implement autotoggling after timeout --- cmd/circologctl/main.go | 12 ++++++++---- cmd/circologd/http_ctl.go | 26 ++++++++++++++++++++++---- cmd/circologd/main.go | 3 ++- hub.go | 22 +++++++++++++++++++--- 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/cmd/circologctl/main.go b/cmd/circologctl/main.go index d95ffe0..0eb7ed9 100644 --- a/cmd/circologctl/main.go +++ b/cmd/circologctl/main.go @@ -9,13 +9,13 @@ import ( "net" "net/http" "os" - "strings" "time" ) var globalOpts struct { ctlSock string verbose bool + debug bool } var ctl http.Client @@ -41,15 +41,18 @@ func init() { //func getCmd(ctlSock string, args []string) error {} func pauseCmd(args []string) error { - var postBody string var dontChangeAgain time.Duration flagset := flag.NewFlagSet(args[0], flag.ExitOnError) waitTime := flagset.Duration("wait-time", dontChangeAgain, "How long to wait before untoggling the state, defaults to never") flagset.Parse(args[1:]) + postBody := make(map[string][]string) if *waitTime != dontChangeAgain { - postBody = fmt.Sprintf("waittime=%s", *waitTime) + postBody["waitTime"] = []string{fmt.Sprintf("%s", *waitTime)} } - resp, err := ctl.Post("http://unix/pause/toggle", "application/octet-stream", strings.NewReader(postBody)) + if globalOpts.debug { + fmt.Println("[DEBUG] postBody:", postBody) + } + resp, err := ctl.PostForm("http://unix/pause/toggle", postBody) if globalOpts.verbose { defer resp.Body.Close() bodyBytes, err := ioutil.ReadAll(resp.Body) @@ -110,6 +113,7 @@ func main() { flag.StringVar(&globalOpts.ctlSock, "ctl-socket", "/tmp/circologd-ctl.sock", "Path to a unix domain socket for the control server; leave empty to disable") flag.BoolVar(&globalOpts.verbose, "verbose", false, "Print more output") + flag.BoolVar(&globalOpts.debug, "debug", false, "Print debugging info") flag.Parse() args := flag.Args() if len(args) == 0 { diff --git a/cmd/circologd/http_ctl.go b/cmd/circologd/http_ctl.go index 75a6223..d47eec8 100644 --- a/cmd/circologd/http_ctl.go +++ b/cmd/circologd/http_ctl.go @@ -6,28 +6,46 @@ import ( "log" "net/http" "os" + "time" fractal "git.lattuga.net/blallo/gotools/formatting" "git.lattuga.net/boyska/circolog" "github.com/gorilla/mux" ) -func setupHTTPCtl(hub circolog.Hub, verbose bool) *mux.Router { +func setupHTTPCtl(hub circolog.Hub, verbose, debug bool) *mux.Router { m := mux.NewRouter() - m.HandleFunc("/pause/toggle", togglePause(hub, verbose)).Methods("POST") + m.HandleFunc("/pause/toggle", togglePause(hub, verbose, debug)).Methods("POST") m.HandleFunc("/logs/clear", clearQueue(hub, verbose)).Methods("POST") m.HandleFunc("/help", printHelp(verbose)).Methods("GET") m.HandleFunc("/echo", echo(verbose)).Methods("GET") return m } -func togglePause(hub circolog.Hub, verbose bool) http.HandlerFunc { +func togglePause(hub circolog.Hub, verbose, debug bool) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if verbose { log.Printf("[%s] %s - toggled pause", r.Method, r.RemoteAddr) } + r.ParseForm() + waitTimePar := r.FormValue("waitTime") + var waitTime time.Duration + var err error + if waitTimePar != "" { + waitTime, err = time.ParseDuration(waitTimePar) + if err != nil { + fmt.Println("waitTime not understood:", waitTimePar) + } + } + if debug { + fmt.Println("[DEBUG] waitTime:", waitTime) + } response := make(chan circolog.CommandResponse) - hub.Commands <- circolog.HubFullCommand{Command: circolog.CommandPauseToggle, Response: response} + hub.Commands <- circolog.HubFullCommand{ + Command: circolog.CommandPauseToggle, + Response: response, + Parameters: map[string]interface{}{"waitTime": waitTime}, + } resp := <-response active := resp.Value.(bool) w.Header().Set("content-type", "application/json") diff --git a/cmd/circologd/main.go b/cmd/circologd/main.go index 09e11cc..cf0a202 100644 --- a/cmd/circologd/main.go +++ b/cmd/circologd/main.go @@ -30,6 +30,7 @@ func main() { querySocket := flag.String("query-socket", "", "Path to a unix domain socket for the HTTP server; recommended for security reasons!") ctlSocket := flag.String("ctl-socket", "/tmp/circologd-ctl.sock", "Path to a unix domain socket for the control server; leave empty to disable") verbose := flag.Bool("verbose", false, "Print more output executing the daemon") + debug := flag.Bool("debug", false, "Print debugging info executing the daemon") flag.Parse() interrupt := make(chan os.Signal, 1) @@ -86,7 +87,7 @@ func main() { }() } - httpCtlServer := http.Server{Handler: setupHTTPCtl(hub, *verbose)} + httpCtlServer := http.Server{Handler: setupHTTPCtl(hub, *verbose, *debug)} if *ctlSocket != "" { fmt.Printf("Binding address `%s` [http]\n", *ctlSocket) unixListener, err := net.Listen("unix", *ctlSocket) diff --git a/hub.go b/hub.go index 61e2a91..7d160c2 100644 --- a/hub.go +++ b/hub.go @@ -2,6 +2,8 @@ package circolog import ( "container/ring" + "fmt" + "os" "time" "gopkg.in/mcuadros/go-syslog.v2/format" @@ -35,8 +37,9 @@ const ( // An HubFullCommand is a Command, complete with arguments type HubFullCommand struct { - Command HubCommand - Response chan CommandResponse + Command HubCommand + Parameters map[string]interface{} + Response chan CommandResponse } type CommandResponse struct { Value interface{} @@ -127,13 +130,26 @@ func (h *Hub) Run() { cmd.Response <- CommandResponse{Value: true} } if cmd.Command == CommandPauseToggle { - active = !active + togglePause(cmd.Parameters["waitTime"].(time.Duration), &active) cmd.Response <- CommandResponse{Value: active} } } } } +func togglePause(waitTime time.Duration, status *bool) { + var noTime time.Duration + if waitTime != noTime { + delayedToggle := func() { + time.Sleep(waitTime) + fmt.Fprintln(os.Stderr, "toggling again") + togglePause(noTime, status) + } + go delayedToggle() + } + *status = !*status +} + // Clear removes all elements from the buffer func (h *Hub) clear() { buf := h.circbuf