From 2eb6da5f21f12cfe21f88673da5be457526db758 Mon Sep 17 00:00:00 2001 From: tidwall Date: Wed, 7 Oct 2020 09:52:32 -0700 Subject: [PATCH] Truncate trailing zeros from AOF at startup This commit addresses issue #230, where an AOF file will sometimes not load due to the file being padded with trailing zeros. It's uncertain what is causing this corruption, but it appears to be coming from outside of the tile38-server process. I suspect it's due to some block store layer in Kubernetes/Docker cloud environments. This fix allows for Tile38 to start up by discovering the trailing zeros while loading the AOF and safely truncating the file as to not include the zeros in the future. --- internal/server/aof.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/internal/server/aof.go b/internal/server/aof.go index cd86f397..83913e01 100644 --- a/internal/server/aof.go +++ b/internal/server/aof.go @@ -32,7 +32,7 @@ func (err errAOFHook) Error() string { var errInvalidAOF = errors.New("invalid aof file") -func (s *Server) loadAOF() error { +func (s *Server) loadAOF() (err error) { fi, err := s.aof.Stat() if err != nil { return err @@ -58,6 +58,7 @@ func (s *Server) loadAOF() error { var buf []byte var args [][]byte var packet [0xFFFF]byte + var zeros int for { n, err := s.aof.Read(packet[:]) if err != nil { @@ -65,6 +66,18 @@ func (s *Server) loadAOF() error { if len(buf) > 0 { return io.ErrUnexpectedEOF } + if zeros > 0 { + // Trailing zeros in AOF. Truncate the file so it's sane. + // See issue #230 for more information. Force a warning. + log.Infof("Truncating %d zeros from AOF (issue #230)", zeros) + s.aofsz -= zeros + if err := s.aof.Truncate(int64(s.aofsz)); err != nil { + return err + } + if _, err := s.aof.Seek(int64(s.aofsz), 0); err != nil { + return err + } + } return nil } return err @@ -76,6 +89,16 @@ func (s *Server) loadAOF() error { } var complete bool for { + if len(data) > 0 { + if data[0] == 0 { + zeros++ + data = data[1:] + continue + } + if zeros > 0 { + return errors.New("Zeros found in AOF file (issue #230)") + } + } complete, args, _, data, err = redcon.ReadNextCommand(data, args[:0]) if err != nil { return err