Skip to content

Commit

Permalink
[FIXED] Do not panic when re-calculating first sequence for SimpleSta…
Browse files Browse the repository at this point in the history
…te when fseq moves ahead of old first. (#4346)

When a lazy simple state has an outdated first that needs to be updated,
if fseq had moved past it would panic.
This was not common but with latest fix prior in can become more common,
hence why it showed up.

Signed-off-by: Derek Collison <derek@nats.io>
  • Loading branch information
derekcollison committed Jul 28, 2023
2 parents 7feebb4 + 4c14be9 commit 5b7c029
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 0 deletions.
2 changes: 2 additions & 0 deletions server/filestore.go
Expand Up @@ -5934,6 +5934,8 @@ func (mb *msgBlock) recalculateFirstForSubj(subj string, startSeq uint64, ss *Si
if startSlot >= len(mb.cache.idx) {
ss.First = ss.Last
return
} else if startSlot < 0 {
startSlot = 0
}

var le = binary.LittleEndian
Expand Down
32 changes: 32 additions & 0 deletions server/filestore_test.go
Expand Up @@ -5537,3 +5537,35 @@ func TestFileStoreRestoreEncryptedWithNoKeyFuncFails(t *testing.T) {
)
require_Error(t, err, errNoMainKey)
}

func TestFileStoreRecaluclateFirstForSubjBug(t *testing.T) {
fs, err := newFileStore(FileStoreConfig{StoreDir: t.TempDir()}, StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage})
require_NoError(t, err)

fs.StoreMsg("foo", nil, nil) // 1
fs.StoreMsg("bar", nil, nil) // 2
fs.StoreMsg("foo", nil, nil) // 3

// Now remove first 2..
fs.RemoveMsg(1)
fs.RemoveMsg(2)

// Now grab first (and only) block.
fs.mu.RLock()
mb := fs.blks[0]
fs.mu.RUnlock()

// Since we lazy update the first, simulate that we have not updated it as of yet.
ss := &SimpleState{Msgs: 1, First: 1, Last: 3, firstNeedsUpdate: true}

mb.mu.Lock()
defer mb.mu.Unlock()

// Flush the cache.
mb.clearCacheAndOffset()
// Now call with start sequence of 1, the old one
// This will panic without the fix.
mb.recalculateFirstForSubj("foo", 1, ss)
// Make sure it was update properly.
require_True(t, *ss == SimpleState{Msgs: 1, First: 3, Last: 3, firstNeedsUpdate: false})
}

0 comments on commit 5b7c029

Please sign in to comment.