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.
This commit is contained in:
tidwall 2020-10-07 09:52:32 -07:00
parent b075cd0db8
commit 2eb6da5f21
1 changed files with 24 additions and 1 deletions

View File

@ -32,7 +32,7 @@ func (err errAOFHook) Error() string {
var errInvalidAOF = errors.New("invalid aof file") var errInvalidAOF = errors.New("invalid aof file")
func (s *Server) loadAOF() error { func (s *Server) loadAOF() (err error) {
fi, err := s.aof.Stat() fi, err := s.aof.Stat()
if err != nil { if err != nil {
return err return err
@ -58,6 +58,7 @@ func (s *Server) loadAOF() error {
var buf []byte var buf []byte
var args [][]byte var args [][]byte
var packet [0xFFFF]byte var packet [0xFFFF]byte
var zeros int
for { for {
n, err := s.aof.Read(packet[:]) n, err := s.aof.Read(packet[:])
if err != nil { if err != nil {
@ -65,6 +66,18 @@ func (s *Server) loadAOF() error {
if len(buf) > 0 { if len(buf) > 0 {
return io.ErrUnexpectedEOF 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 nil
} }
return err return err
@ -76,6 +89,16 @@ func (s *Server) loadAOF() error {
} }
var complete bool var complete bool
for { 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]) complete, args, _, data, err = redcon.ReadNextCommand(data, args[:0])
if err != nil { if err != nil {
return err return err