<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"time"

	pb "github.com/codeskyblue/gosuv/gosuvpb"
	"github.com/lunny/tango"
	"github.com/qiniu/log"
	"google.golang.org/grpc"
)

type JSONResponse struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

func renderJSON(w http.ResponseWriter, v interface{}) {
	w.Header().Add("Content-Type", "json")
	json.NewEncoder(w).Encode(v)
}

func versionHandler(w http.ResponseWriter, r *http.Request) {
	renderJSON(w, &JSONResponse{
		Code:    200,
		Message: GOSUV_VERSION,
	})
}

func statusHandler(w http.ResponseWriter, r *http.Request) {
	prms := programTable.Programs()
	renderJSON(w, prms)
}

func addHandler(w http.ResponseWriter, r *http.Request) {
	pinfo := new(ProgramInfo)
	err := json.NewDecoder(r.Body).Decode(pinfo)
	if err != nil {
		http.Error(w, err.Error(), 502)
		return
	}
	log.Printf("add: %#v", pinfo)

	program := NewProgram(pinfo)
	if err = programTable.AddProgram(program); err != nil {
		http.Error(w, err.Error(), 503)
		return
	}
	program.InputData(EVENT_START)

	renderJSON(w, &JSONResponse{
		Code:    200,
		Message: "program add success",
	})
}

func shutdownHandler(w http.ResponseWriter, r *http.Request) {
	go func() {
		time.Sleep(50 * time.Millisecond)
		os.Exit(2)
	}()
	renderJSON(w, &JSONResponse{
		Code:    200,
		Message: "not implement",
	})
}

func handleSignal(lis net.Listener) {
	sigc := make(chan os.Signal, 2)
	signal.Notify(sigc, syscall.SIGINT, syscall.SIGHUP)
	go func() {
		for sig := range sigc {
			log.Println("Receive signal:", sig)
			if sig == syscall.SIGHUP {
				return // ignore
			}
			lis.Close()
			programTable.StopAll()
			os.Exit(0)
			return
		}
	}()
}

func ServeAddr(addr string) error {
	InitServer()

	t := tango.New()
	t.Group("/api", func(g *tango.Group) {
		g.Get("/version", versionHandler)
		g.Post("/shutdown", shutdownHandler)
		g.Post("/programs", addHandler)
		g.Get("/programs", statusHandler)
	})

	go t.Run(addr)

	lis, err := net.Listen("unix", filepath.Join(GOSUV_HOME, "gosuv.sock"))
	if err != nil {
		log.Fatal(err)
	}
	handleSignal(lis)<commit_msg>shutdown web server<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"

	pb "github.com/codeskyblue/gosuv/gosuvpb"
	"github.com/qiniu/log"
	"google.golang.org/grpc"
)

type JSONResponse struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

func renderJSON(w http.ResponseWriter, v interface{}) {
	w.Header().Add("Content-Type", "json")
	json.NewEncoder(w).Encode(v)
}

/*
func versionHandler(w http.ResponseWriter, r *http.Request) {
	renderJSON(w, &JSONResponse{
		Code:    200,
		Message: GOSUV_VERSION,
	})
}

func statusHandler(w http.ResponseWriter, r *http.Request) {
	prms := programTable.Programs()
	renderJSON(w, prms)
}

func addHandler(w http.ResponseWriter, r *http.Request) {
	pinfo := new(ProgramInfo)
	err := json.NewDecoder(r.Body).Decode(pinfo)
	if err != nil {
		http.Error(w, err.Error(), 502)
		return
	}
	log.Printf("add: %#v", pinfo)

	program := NewProgram(pinfo)
	if err = programTable.AddProgram(program); err != nil {
		http.Error(w, err.Error(), 503)
		return
	}
	program.InputData(EVENT_START)

	renderJSON(w, &JSONResponse{
		Code:    200,
		Message: "program add success",
	})
}

func shutdownHandler(w http.ResponseWriter, r *http.Request) {
	go func() {
		time.Sleep(50 * time.Millisecond)
		os.Exit(2)
	}()
	renderJSON(w, &JSONResponse{
		Code:    200,
		Message: "not implement",
	})
}
*/

func handleSignal(lis net.Listener) {
	sigc := make(chan os.Signal, 2)
	signal.Notify(sigc, syscall.SIGINT, syscall.SIGHUP)
	go func() {
		for sig := range sigc {
			log.Println("Receive signal:", sig)
			if sig == syscall.SIGHUP {
				return // ignore
			}
			lis.Close()
			programTable.StopAll()
			os.Exit(0)
			return
		}
	}()
}

func ServeAddr(addr string) error {
	InitServer()

	/*
		t := tango.New()
		t.Group("/api", func(g *tango.Group) {
			g.Get("/version", versionHandler)
			g.Post("/shutdown", shutdownHandler)
			g.Post("/programs", addHandler)
			g.Get("/programs", statusHandler)
		})

		go t.Run(addr)
	*/

	lis, err := net.Listen("unix", filepath.Join(GOSUV_HOME, "gosuv.sock"))
	if err != nil {
		log.Fatal(err)
	}
	handleSignal(lis)
{'fraction_non_alphanumeric': 0.16643709825528008, 'fraction_numerical': 0.009182736455463728, 'mean_word_length': 3.939909297052154, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5634994', 'n_tokens_mistral': 1833, 'n_tokens_neox': 1674, 'n_words': 335}