diff --git a/cmd/tile38-server/main.go b/cmd/tile38-server/main.go index 4bdf14be..f57be134 100644 --- a/cmd/tile38-server/main.go +++ b/cmd/tile38-server/main.go @@ -53,6 +53,42 @@ func (s *hserver) Send(ctx context.Context, in *hservice.MessageRequest) (*hserv } func main() { + gitsha := " (" + core.GitSHA + ")" + if gitsha == " (0000000)" { + gitsha = "" + } + versionLine := `tile38-server version: ` + core.Version + gitsha + + output := os.Stderr + flag.Usage = func() { + fmt.Fprintf(output, + versionLine+` + +Usage: tile38-server [-p port] + +Basic Options: + -h hostname : listening host + -p port : listening port (default: 9851) + -d path : data directory (default: data) + -q : no logging. totally silent output + -v : enable verbose logging + -vv : enable very verbose logging + +Advanced Options: + --pidfile path : file that contains the pid + --appendonly yes/no : AOF persistence (default: yes) + --appendonlyfile path : AOF path (default: data/appendonly.aof) + --http-transport yes/no : HTTP transport (default: yes) + --protected-mode yes/no : protected mode (default: yes) + +Developer Options: + --dev : enable developer mode + --webhook-http-consumer-port port : Start a test HTTP webhook server + --webhook-grpc-consumer-port port : Start a test GRPC webhook server +`, + ) + } + if len(os.Args) == 3 && os.Args[1] == "--webhook-http-consumer-port" { log.SetOutput(os.Stderr) port, err := strconv.ParseUint(os.Args[2], 10, 16) @@ -97,6 +133,13 @@ func main() { nargs := []string{os.Args[0]} for i := 1; i < len(os.Args); i++ { switch os.Args[i] { + case "--help": + output = os.Stdout + flag.Usage() + return + case "--version": + fmt.Fprintf(os.Stdout, "%s\n", versionLine) + return case "--protected-mode", "-protected-mode": i++ if i < len(os.Args) { @@ -113,6 +156,26 @@ func main() { case "--dev", "-dev": devMode = true continue + case "--appendonly", "-appendonly": + i++ + if i < len(os.Args) { + switch strings.ToLower(os.Args[i]) { + case "no": + core.AppendOnly = "no" + case "yes": + core.AppendOnly = "yes" + } + continue + } + fmt.Fprintf(os.Stderr, "appendonly must be 'yes' or 'no'\n") + os.Exit(1) + case "--appendfilename", "-appendfilename": + i++ + if i == len(os.Args) || os.Args[i] == "" { + fmt.Fprintf(os.Stderr, "appendfilename must have a value\n") + os.Exit(1) + } + core.AppendFileName = os.Args[i] case "--http-transport", "-http-transport": i++ if i < len(os.Args) { @@ -161,10 +224,6 @@ func main() { if host != "" { hostd = "Addr: " + host + ", " } - gitsha := " (" + core.GitSHA + ")" - if gitsha == " (0000000)" { - gitsha = "" - } var pidferr error var cleanedup bool diff --git a/controller/aof.go b/controller/aof.go index 7a384ccf..7381e874 100644 --- a/controller/aof.go +++ b/controller/aof.go @@ -165,11 +165,13 @@ func (c *Controller) writeAOF(value resp.Value, d *commandDetailsT) error { if err != nil { return err } - n, err := c.aof.Write(data) - if err != nil { - return err + if c.aof != nil { + n, err := c.aof.Write(data) + if err != nil { + return err + } + c.aofsz += n } - c.aofsz += n // notify aof live connections that we have new data c.fcond.L.Lock() @@ -298,6 +300,9 @@ func (c *Controller) cmdAOFMD5(msg *server.Message) (res resp.Value, err error) } func (c *Controller) cmdAOF(msg *server.Message) (res resp.Value, err error) { + if c.aof == nil { + return server.NOMessage, errors.New("aof disabled") + } vs := msg.Values[1:] var ok bool diff --git a/controller/aofshrink.go b/controller/aofshrink.go index 74f5b678..3e5afe49 100644 --- a/controller/aofshrink.go +++ b/controller/aofshrink.go @@ -3,7 +3,6 @@ package controller import ( "math" "os" - "path" "sort" "strconv" "strings" @@ -11,6 +10,7 @@ import ( "github.com/tidwall/tile38/controller/collection" "github.com/tidwall/tile38/controller/log" + "github.com/tidwall/tile38/core" "github.com/tidwall/tile38/geojson" ) @@ -19,6 +19,9 @@ const maxids = 32 const maxchunk = 4 * 1024 * 1024 func (c *Controller) aofshrink() { + if c.aof == nil { + return + } start := time.Now() c.mu.Lock() if c.shrinking { @@ -39,7 +42,7 @@ func (c *Controller) aofshrink() { }() err := func() error { - f, err := os.Create(path.Join(c.dir, "shrink")) + f, err := os.Create(core.AppendFileName + "-shrink") if err != nil { return err } @@ -255,13 +258,13 @@ func (c *Controller) aofshrink() { if err := c.aof.Close(); err != nil { log.Fatalf("shrink live aof close fatal operation: %v", err) } - if err := os.Rename(path.Join(c.dir, "appendonly.aof"), path.Join(c.dir, "appendonly.bak")); err != nil { + if err := os.Rename(core.AppendFileName, core.AppendFileName+"-bak"); err != nil { log.Fatalf("shrink backup fatal operation: %v", err) } - if err := os.Rename(path.Join(c.dir, "shrink"), path.Join(c.dir, "appendonly.aof")); err != nil { + if err := os.Rename(core.AppendFileName+"-shrink", core.AppendFileName); err != nil { log.Fatalf("shrink rename fatal operation: %v", err) } - c.aof, err = os.OpenFile(path.Join(c.dir, "appendonly.aof"), os.O_CREATE|os.O_RDWR, 0600) + c.aof, err = os.OpenFile(core.AppendFileName, os.O_CREATE|os.O_RDWR, 0600) if err != nil { log.Fatalf("shrink openfile fatal operation: %v", err) } @@ -272,7 +275,7 @@ func (c *Controller) aofshrink() { } c.aofsz = int(n) - os.Remove(path.Join(c.dir, "appendonly.bak")) // ignore error + os.Remove(core.AppendFileName + "-bak") // ignore error // kill all followers connections for conn := range c.aofconnM { diff --git a/controller/controller.go b/controller/controller.go index 89402726..6a507e73 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -116,6 +116,10 @@ func ListenAndServe(host string, port int, dir string, http bool) error { return ListenAndServeEx(host, port, dir, nil, http) } func ListenAndServeEx(host string, port int, dir string, ln *net.Listener, http bool) error { + if core.AppendFileName == "" { + core.AppendFileName = path.Join(dir, "appendonly.aof") + } + log.Infof("Server started, Tile38 version %s, git %s", core.Version, core.GitSHA) c := &Controller{ host: host, @@ -177,13 +181,15 @@ func ListenAndServeEx(host string, port int, dir string, ln *net.Listener, http if err := c.migrateAOF(); err != nil { return err } - f, err := os.OpenFile(path.Join(dir, "appendonly.aof"), os.O_CREATE|os.O_RDWR, 0600) - if err != nil { - return err - } - c.aof = f - if err := c.loadAOF(); err != nil { - return err + if core.AppendOnly == "yes" { + f, err := os.OpenFile(core.AppendFileName, os.O_CREATE|os.O_RDWR, 0600) + if err != nil { + return err + } + c.aof = f + if err := c.loadAOF(); err != nil { + return err + } } c.fillExpiresList() if c.config.followHost() != "" { diff --git a/core/options.go b/core/options.go index dd67acf3..1e62a9b1 100644 --- a/core/options.go +++ b/core/options.go @@ -8,3 +8,9 @@ var ShowDebugMessages = false // ProtectedMode forces Tile38 to default in protected mode. var ProtectedMode = "yes" + +// AppendOnly allows for disabling the appendonly file. +var AppendOnly = "yes" + +// AppendFileName allows for custom appendonly file path +var AppendFileName string