浏览代码

refactor serve.go to use the new API

flashmob 8 年之前
父节点
当前提交
7043262c11
共有 4 个文件被更改,包括 50 次插入121 次删除
  1. 7 8
      api.go
  2. 13 1
      api_test.go
  3. 23 105
      cmd/guerrillad/serve.go
  4. 7 7
      guerrilla.go

+ 7 - 8
api.go

@@ -74,21 +74,21 @@ func (d *Daemon) Shutdown() {
 	}
 	}
 }
 }
 
 
-// ReadConfig reads in the config from a JSON file.
-func (d *Daemon) ReadConfig(path string) error {
+// LoadConfig reads in the config from a JSON file.
+func (d *Daemon) LoadConfig(path string) (AppConfig, error) {
 	data, err := ioutil.ReadFile(path)
 	data, err := ioutil.ReadFile(path)
 	if err != nil {
 	if err != nil {
-		return fmt.Errorf("Could not read config file: %s", err.Error())
+		return *d.Config, fmt.Errorf("Could not read config file: %s", err.Error())
 	}
 	}
 	d.Config = &AppConfig{}
 	d.Config = &AppConfig{}
 	if err := d.Config.Load(data); err != nil {
 	if err := d.Config.Load(data); err != nil {
-		return err
+		return *d.Config, err
 	}
 	}
 	d.configLoadTime = time.Now()
 	d.configLoadTime = time.Now()
-	return nil
+	return *d.Config, nil
 }
 }
 
 
-// SetConfig is same as ReadConfig, except you can pass AppConfig directly
+// SetConfig is same as LoadConfig, except you can pass AppConfig directly
 func (d *Daemon) SetConfig(c AppConfig) error {
 func (d *Daemon) SetConfig(c AppConfig) error {
 	// Config.Load takes []byte so we need to serialize
 	// Config.Load takes []byte so we need to serialize
 	data, err := json.Marshal(c)
 	data, err := json.Marshal(c)
@@ -128,8 +128,7 @@ func (d *Daemon) ReloadConfigFile(path string) error {
 	}
 	}
 	var oldConfig AppConfig
 	var oldConfig AppConfig
 	oldConfig = *d.Config
 	oldConfig = *d.Config
-	err := d.ReadConfig(path)
-
+	_, err := d.LoadConfig(path)
 	if err != nil {
 	if err != nil {
 		d.log().WithError(err).Error("Error while reloading config from file")
 		d.log().WithError(err).Error("Error while reloading config from file")
 		return err
 		return err

+ 13 - 1
api_test.go

@@ -10,6 +10,18 @@ import (
 
 
 // Test Starting smtp without setting up logger / backend
 // Test Starting smtp without setting up logger / backend
 func TestSMTP(t *testing.T) {
 func TestSMTP(t *testing.T) {
+	go func() {
+		select {
+		case <-time.After(time.Second * 40):
+			//buf := make([]byte, 1<<16)
+			//stackSize := runtime.Stack(buf, true)
+			//fmt.Printf("%s\n", string(buf[0:stackSize]))
+			//panic("timeout")
+			t.Error("timeout")
+			return
+
+		}
+	}()
 
 
 	d := Daemon{}
 	d := Daemon{}
 	err := d.Start()
 	err := d.Start()
@@ -163,7 +175,7 @@ func TestSMTPLoadFile(t *testing.T) {
 	}
 	}
 
 
 	d := Daemon{}
 	d := Daemon{}
-	err = d.ReadConfig("goguerrilla.conf.api")
+	_, err = d.LoadConfig("goguerrilla.conf.api")
 	if err != nil {
 	if err != nil {
 		t.Error("ReadConfig error", err)
 		t.Error("ReadConfig error", err)
 		return
 		return

+ 23 - 105
cmd/guerrillad/serve.go

@@ -2,20 +2,16 @@ package main
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
-	"errors"
 	"fmt"
 	"fmt"
 	"github.com/flashmob/go-guerrilla"
 	"github.com/flashmob/go-guerrilla"
-	"github.com/flashmob/go-guerrilla/backends"
 	"github.com/flashmob/go-guerrilla/log"
 	"github.com/flashmob/go-guerrilla/log"
 	"github.com/spf13/cobra"
 	"github.com/spf13/cobra"
-	"io/ioutil"
 	"os"
 	"os"
 	"os/exec"
 	"os/exec"
 	"os/signal"
 	"os/signal"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 	"syscall"
 	"syscall"
-	"time"
 )
 )
 
 
 const (
 const (
@@ -33,29 +29,29 @@ var (
 	}
 	}
 
 
 	cmdConfig     = CmdConfig{}
 	cmdConfig     = CmdConfig{}
-	signalChannel = make(chan os.Signal, 1) // for trapping SIG_HUP
+	signalChannel = make(chan os.Signal, 1) // for trapping SIGHUP and friends
 	mainlog       log.Logger
 	mainlog       log.Logger
+
+	d guerrilla.Daemon
 )
 )
 
 
 func init() {
 func init() {
 	// log to stderr on startup
 	// log to stderr on startup
-	var logOpenError error
-	if mainlog, logOpenError = log.GetLogger(log.OutputStderr.String()); logOpenError != nil {
-		mainlog.WithError(logOpenError).Errorf("Failed creating a logger to %s", log.OutputStderr)
+	var err error
+	mainlog, err = log.GetLogger(log.OutputStderr.String())
+	if err != nil {
+		mainlog.WithError(err).Errorf("Failed creating a logger to %s", log.OutputStderr)
 	}
 	}
 	serveCmd.PersistentFlags().StringVarP(&configPath, "config", "c",
 	serveCmd.PersistentFlags().StringVarP(&configPath, "config", "c",
 		"goguerrilla.conf", "Path to the configuration file")
 		"goguerrilla.conf", "Path to the configuration file")
 	// intentionally didn't specify default pidFile; value from config is used if flag is empty
 	// intentionally didn't specify default pidFile; value from config is used if flag is empty
 	serveCmd.PersistentFlags().StringVarP(&pidFile, "pidFile", "p",
 	serveCmd.PersistentFlags().StringVarP(&pidFile, "pidFile", "p",
 		"", "Path to the pid file")
 		"", "Path to the pid file")
-
 	rootCmd.AddCommand(serveCmd)
 	rootCmd.AddCommand(serveCmd)
 }
 }
 
 
-func sigHandler(app guerrilla.Guerrilla) {
-
-	signal.Notify(
-		signalChannel,
+func sigHandler() {
+	signal.Notify(signalChannel,
 		syscall.SIGHUP,
 		syscall.SIGHUP,
 		syscall.SIGTERM,
 		syscall.SIGTERM,
 		syscall.SIGQUIT,
 		syscall.SIGQUIT,
@@ -63,27 +59,14 @@ func sigHandler(app guerrilla.Guerrilla) {
 		syscall.SIGKILL,
 		syscall.SIGKILL,
 		syscall.SIGUSR1,
 		syscall.SIGUSR1,
 	)
 	)
-
 	for sig := range signalChannel {
 	for sig := range signalChannel {
 		if sig == syscall.SIGHUP {
 		if sig == syscall.SIGHUP {
-			// save old config & load in new one
-			oldConfig := cmdConfig
-			newConfig := CmdConfig{}
-			err := readConfig(configPath, pidFile, &newConfig)
-			if err != nil {
-				// new config will not be applied
-				mainlog.WithError(err).Error("Error while ReadConfig (reload)")
-			} else {
-				cmdConfig = newConfig
-				mainlog.Infof("Configuration was reloaded at %s", guerrilla.ConfigLoadTime)
-				cmdConfig.emitChangeEvents(&oldConfig, app)
-			}
+			d.ReloadConfigFile(configPath)
 		} else if sig == syscall.SIGUSR1 {
 		} else if sig == syscall.SIGUSR1 {
-			// re-open logs
-			cmdConfig.EmitLogReopenEvents(app)
+			d.ReopenLogs()
 		} else if sig == syscall.SIGTERM || sig == syscall.SIGQUIT || sig == syscall.SIGINT {
 		} else if sig == syscall.SIGTERM || sig == syscall.SIGQUIT || sig == syscall.SIGINT {
 			mainlog.Infof("Shutdown signal caught")
 			mainlog.Infof("Shutdown signal caught")
-			app.Shutdown()
+			d.Shutdown()
 			mainlog.Infof("Shutdown completed, exiting.")
 			mainlog.Infof("Shutdown completed, exiting.")
 			return
 			return
 		} else {
 		} else {
@@ -95,8 +78,8 @@ func sigHandler(app guerrilla.Guerrilla) {
 
 
 func serve(cmd *cobra.Command, args []string) {
 func serve(cmd *cobra.Command, args []string) {
 	logVersion()
 	logVersion()
-
-	err := readConfig(configPath, pidFile, &cmdConfig)
+	d = guerrilla.Daemon{Logger: mainlog}
+	err := readConfig(configPath, pidFile)
 	if err != nil {
 	if err != nil {
 		mainlog.WithError(err).Fatal("Error while reading config")
 		mainlog.WithError(err).Fatal("Error while reading config")
 	}
 	}
@@ -116,53 +99,12 @@ func serve(cmd *cobra.Command, args []string) {
 		}
 		}
 	}
 	}
 
 
-	// Backend setup
-	var backend backends.Backend
-	backend, err = backends.New(cmdConfig.BackendConfig, mainlog)
-	if err != nil {
-		mainlog.WithError(err).Fatalf("Error while loading the backend")
-	}
-	/*
-		// add our custom processor to the backend
-		backends.Service.AddProcessor("MailDir", maildiranasaurus.MaildirProcessor)
-		config := guerrilla.AppConfig {
-			LogFile: log.OutputStderr,
-			LogLevel: "info",
-			AllowedHosts: []string{"example.com"},
-			PidFile: "./pidfile.pid",
-			Servers: []guerrilla.ServerConfig{
-
-			}
-		}
-	*/
-
-	//	g := guerrilla.NewSMTPD{config: cmdConfig}
-
-	app, err := guerrilla.New(&cmdConfig.AppConfig, backend, mainlog)
+	err = d.Start()
 	if err != nil {
 	if err != nil {
 		mainlog.WithError(err).Error("Error(s) when creating new server(s)")
 		mainlog.WithError(err).Error("Error(s) when creating new server(s)")
+		os.Exit(1)
 	}
 	}
-
-	// start the app
-	err = app.Start()
-	if err != nil {
-		mainlog.WithError(err).Error("Error(s) when starting server(s)")
-	}
-
-	// Write out our PID
-	writePid(cmdConfig.PidFile)
-	// ...and write out our pid whenever the file name changes in the config
-	app.Subscribe(guerrilla.EventConfigPidFile, func(ac *guerrilla.AppConfig) {
-		writePid(ac.PidFile)
-	})
-	// change the logger from stdrerr to one from config
-	mainlog.Infof("main log configured to %s", cmdConfig.LogFile)
-	var logOpenError error
-	if mainlog, logOpenError = log.GetLogger(cmdConfig.LogFile); logOpenError != nil {
-		mainlog.WithError(logOpenError).Errorf("Failed changing to a custom logger [%s]", cmdConfig.LogFile)
-	}
-	app.SetLogger(mainlog)
-	sigHandler(app)
+	sigHandler()
 
 
 }
 }
 
 
@@ -190,29 +132,22 @@ func (c *CmdConfig) emitChangeEvents(oldConfig *CmdConfig, app guerrilla.Guerril
 }
 }
 
 
 // ReadConfig which should be called at startup, or when a SIG_HUP is caught
 // ReadConfig which should be called at startup, or when a SIG_HUP is caught
-func readConfig(path string, pidFile string, config *CmdConfig) error {
+func readConfig(path string, pidFile string) error {
 	// Load in the config.
 	// Load in the config.
 	// Note here is the only place we can make an exception to the
 	// Note here is the only place we can make an exception to the
 	// "treat config values as immutable". For example, here the
 	// "treat config values as immutable". For example, here the
 	// command line flags can override config values
 	// command line flags can override config values
-	data, err := ioutil.ReadFile(path)
+	appConfig, err := d.LoadConfig(path)
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("Could not read config file: %s", err.Error())
 		return fmt.Errorf("Could not read config file: %s", err.Error())
 	}
 	}
-	if err := config.load(data); err != nil {
-		return err
-	}
 	// override config pidFile with with flag from the command line
 	// override config pidFile with with flag from the command line
 	if len(pidFile) > 0 {
 	if len(pidFile) > 0 {
-		config.AppConfig.PidFile = pidFile
-	} else if len(config.AppConfig.PidFile) == 0 {
-		config.AppConfig.PidFile = defaultPidFile
-	}
-
-	if len(config.AllowedHosts) == 0 {
-		return errors.New("Empty `allowed_hosts` is not allowed")
+		appConfig.PidFile = pidFile
+	} else if len(appConfig.PidFile) == 0 {
+		appConfig.PidFile = defaultPidFile
 	}
 	}
-	guerrilla.ConfigLoadTime = time.Now()
+	d.SetConfig(appConfig)
 	return nil
 	return nil
 }
 }
 
 
@@ -228,20 +163,3 @@ func getFileLimit() int {
 	}
 	}
 	return limit
 	return limit
 }
 }
-
-func writePid(pidFile string) {
-	if len(pidFile) > 0 {
-		if f, err := os.Create(pidFile); err == nil {
-			defer f.Close()
-			pid := os.Getpid()
-			if _, err := f.WriteString(fmt.Sprintf("%d", pid)); err == nil {
-				f.Sync()
-				mainlog.Infof("(serve.go) pid_file (%s) written with pid:%v", pidFile, pid)
-			} else {
-				mainlog.WithError(err).Fatalf("Error while writing pidFile (%s)", pidFile)
-			}
-		} else {
-			mainlog.WithError(err).Fatalf("Error while creating pidFile (%s)", pidFile)
-		}
-	}
-}

+ 7 - 7
guerrilla.go

@@ -109,8 +109,6 @@ func New(ac *AppConfig, b backends.Backend, l log.Logger) (Guerrilla, error) {
 // Instantiate servers
 // Instantiate servers
 func (g *guerrilla) makeServers() error {
 func (g *guerrilla) makeServers() error {
 	g.mainlog().Debug("making servers")
 	g.mainlog().Debug("making servers")
-	g.guard.Lock()
-	defer g.guard.Unlock()
 	var errs Errors
 	var errs Errors
 	for _, sc := range g.Config.Servers {
 	for _, sc := range g.Config.Servers {
 		if _, ok := g.servers[sc.ListenInterface]; ok {
 		if _, ok := g.servers[sc.ListenInterface]; ok {
@@ -450,11 +448,8 @@ func (g *guerrilla) Start() error {
 }
 }
 
 
 func (g *guerrilla) Shutdown() {
 func (g *guerrilla) Shutdown() {
-	g.guard.Lock()
-	defer func() {
-		g.state = GuerrillaStateStopped
-		defer g.guard.Unlock()
-	}()
+
+	// shot down the servers first
 	g.mapServers(func(s *server) {
 	g.mapServers(func(s *server) {
 		if s.state == ServerStateRunning {
 		if s.state == ServerStateRunning {
 			s.Shutdown()
 			s.Shutdown()
@@ -462,6 +457,11 @@ func (g *guerrilla) Shutdown() {
 		}
 		}
 	})
 	})
 
 
+	g.guard.Lock()
+	defer func() {
+		g.state = GuerrillaStateStopped
+		defer g.guard.Unlock()
+	}()
 	if err := g.backend().Shutdown(); err != nil {
 	if err := g.backend().Shutdown(); err != nil {
 		g.mainlog().WithError(err).Warn("Backend failed to shutdown")
 		g.mainlog().WithError(err).Warn("Backend failed to shutdown")
 	} else {
 	} else {