Skip to content

Commit afa7427

Browse files
committed
add locking to cached Put
1 parent 20b70f1 commit afa7427

File tree

2 files changed

+20
-3
lines changed

2 files changed

+20
-3
lines changed

x/blockdb/cache_db.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,25 @@ package blockdb
55

66
import (
77
"slices"
8+
"sync"
89

910
"go.uber.org/zap"
1011

1112
"github.com/ava-labs/avalanchego/cache/lru"
1213
"github.com/ava-labs/avalanchego/database"
1314
)
1415

16+
// numShards is the number of mutex shards used to reduce lock contention for
17+
// concurrent Put operations. Using 256 shards provides a good balance between
18+
// memory usage (~2KB) and concurrency.
19+
const numShards = 256
20+
1521
var _ database.HeightIndex = (*cacheDB)(nil)
1622

1723
type cacheDB struct {
18-
db *Database
19-
cache *lru.Cache[BlockHeight, BlockData]
24+
db *Database
25+
cache *lru.Cache[BlockHeight, BlockData]
26+
shards [numShards]sync.Mutex
2027
}
2128

2229
func newCacheDB(db *Database, size uint16) *cacheDB {
@@ -46,7 +53,18 @@ func (c *cacheDB) Get(height BlockHeight) (BlockData, error) {
4653
return data, nil
4754
}
4855

56+
// Put writes block data at the specified height to both the underlying database
57+
// and the cache.
58+
//
59+
// Concurrent calls to Put with the same height are serialized using sharded
60+
// locking to ensure cache consistency with the underlying database.
61+
// This allows concurrent writes to different heights while preventing race
62+
// conditions for writes to the same height.
4963
func (c *cacheDB) Put(height BlockHeight, data BlockData) error {
64+
shard := &c.shards[height%numShards]
65+
shard.Lock()
66+
defer shard.Unlock()
67+
5068
if err := c.db.Put(height, data); err != nil {
5169
return err
5270
}

x/blockdb/cache_db_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ func TestCachePutOverridesSameHeight(t *testing.T) {
110110
cached, ok = db.cache.Get(height)
111111
require.True(t, ok)
112112
require.Equal(t, b2, cached)
113-
require.NotEqual(t, b1, cached)
114113

115114
// Get should also return the new block
116115
data, err := db.Get(height)

0 commit comments

Comments
 (0)