Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions fastcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,9 +393,12 @@ func (b *bucket) Get(dst, k []byte, h uint64, returnDst bool) ([]byte, bool) {
goto end
}
chunk := chunks[chunkIdx]
if chunk == nil {
atomic.AddUint64(&b.corruptions, 1)
goto end
}
idx %= chunkSize
if idx+4 >= chunkSize {
// Corrupted data during the load from file. Just skip it.
atomic.AddUint64(&b.corruptions, 1)
goto end
}
Expand All @@ -404,7 +407,6 @@ func (b *bucket) Get(dst, k []byte, h uint64, returnDst bool) ([]byte, bool) {
valLen := (uint64(kvLenBuf[2]) << 8) | uint64(kvLenBuf[3])
idx += 4
if idx+keyLen+valLen >= chunkSize {
// Corrupted data during the load from file. Just skip it.
atomic.AddUint64(&b.corruptions, 1)
goto end
}
Expand Down
34 changes: 34 additions & 0 deletions fastcache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"sync"
"testing"
"time"

xxhash "github.com/cespare/xxhash/v2"
)

func TestCacheSmall(t *testing.T) {
Expand Down Expand Up @@ -222,6 +224,38 @@ func testCacheGetSet(c *Cache, itemsCount int) error {
return nil
}

func TestBucketGetNilChunkNoCorruptionPanic(t *testing.T) {
var b bucket
b.Init(64 * 1024)

k := []byte("testkey")
v := []byte("testvalue")
h := xxhash.Sum64(k)
b.Set(k, v, h)

got, found := b.Get(nil, k, h, true)
if !found || string(got) != "testvalue" {
t.Fatalf("expected to find key before corruption; found=%v val=%q", found, got)
}

b.mu.Lock()
mapVal := b.m[h]
chunkIdx := (mapVal & ((1 << bucketSizeBits) - 1)) / chunkSize
b.chunks[chunkIdx] = nil
b.mu.Unlock()

got, found = b.Get(nil, k, h, true)
if found {
t.Fatalf("expected miss for nil chunk, but got found=true val=%q", got)
}

var s Stats
b.UpdateStats(&s)
if s.Corruptions != 1 {
t.Fatalf("expected 1 corruption; got %d", s.Corruptions)
}
}

func TestCacheResetUpdateStatsSetConcurrent(t *testing.T) {
c := New(12334)

Expand Down
Loading