Skip to content

Commit 5b7c029

Browse files
[FIXED] Do not panic when re-calculating first sequence for SimpleState 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>
2 parents 7feebb4 + 4c14be9 commit 5b7c029

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

server/filestore.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5934,6 +5934,8 @@ func (mb *msgBlock) recalculateFirstForSubj(subj string, startSeq uint64, ss *Si
59345934
if startSlot >= len(mb.cache.idx) {
59355935
ss.First = ss.Last
59365936
return
5937+
} else if startSlot < 0 {
5938+
startSlot = 0
59375939
}
59385940

59395941
var le = binary.LittleEndian

server/filestore_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5537,3 +5537,35 @@ func TestFileStoreRestoreEncryptedWithNoKeyFuncFails(t *testing.T) {
55375537
)
55385538
require_Error(t, err, errNoMainKey)
55395539
}
5540+
5541+
func TestFileStoreRecaluclateFirstForSubjBug(t *testing.T) {
5542+
fs, err := newFileStore(FileStoreConfig{StoreDir: t.TempDir()}, StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage})
5543+
require_NoError(t, err)
5544+
5545+
fs.StoreMsg("foo", nil, nil) // 1
5546+
fs.StoreMsg("bar", nil, nil) // 2
5547+
fs.StoreMsg("foo", nil, nil) // 3
5548+
5549+
// Now remove first 2..
5550+
fs.RemoveMsg(1)
5551+
fs.RemoveMsg(2)
5552+
5553+
// Now grab first (and only) block.
5554+
fs.mu.RLock()
5555+
mb := fs.blks[0]
5556+
fs.mu.RUnlock()
5557+
5558+
// Since we lazy update the first, simulate that we have not updated it as of yet.
5559+
ss := &SimpleState{Msgs: 1, First: 1, Last: 3, firstNeedsUpdate: true}
5560+
5561+
mb.mu.Lock()
5562+
defer mb.mu.Unlock()
5563+
5564+
// Flush the cache.
5565+
mb.clearCacheAndOffset()
5566+
// Now call with start sequence of 1, the old one
5567+
// This will panic without the fix.
5568+
mb.recalculateFirstForSubj("foo", 1, ss)
5569+
// Make sure it was update properly.
5570+
require_True(t, *ss == SimpleState{Msgs: 1, First: 3, Last: 3, firstNeedsUpdate: false})
5571+
}

0 commit comments

Comments
 (0)