Skip to content
This repository was archived by the owner on Jun 19, 2023. It is now read-only.

Commit b34f205

Browse files
committed
fixup! fix(arc): striped locking on last byte of CID
1 parent 72ade3e commit b34f205

File tree

1 file changed

+37
-15
lines changed

1 file changed

+37
-15
lines changed

arc_cache.go

+37-15
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type cacheSize int
1919
// to short-cut many searches without querying the underlying datastore.
2020
type arccache struct {
2121
cache *lru.TwoQueueCache
22-
lks [256]sync.Mutex
22+
lks [256]sync.RWMutex
2323

2424
blockstore Blockstore
2525
viewer Viewer
@@ -36,7 +36,7 @@ func newARCCachedBS(ctx context.Context, bs Blockstore, lruSize int) (*arccache,
3636
if err != nil {
3737
return nil, err
3838
}
39-
c := &arccache{cache: cache, lks: [256]sync.Mutex{}, blockstore: bs}
39+
c := &arccache{cache: cache, blockstore: bs}
4040
c.hits = metrics.NewCtx(ctx, "arc.hits_total", "Number of ARC cache hits").Counter()
4141
c.total = metrics.NewCtx(ctx, "arc_total", "Total number of ARC cache requests").Counter()
4242
if v, ok := bs.(Viewer); ok {
@@ -45,13 +45,27 @@ func newARCCachedBS(ctx context.Context, bs Blockstore, lruSize int) (*arccache,
4545
return c, nil
4646
}
4747

48+
func (b *arccache) rLock(k cid.Cid) func() {
49+
b.lks[k.KeyString()[len(k.KeyString())-1]].RLock()
50+
return func() {
51+
b.lks[k.KeyString()[len(k.KeyString())-1]].RUnlock()
52+
}
53+
}
54+
55+
func (b *arccache) wLock(k cid.Cid) func() {
56+
b.lks[k.KeyString()[len(k.KeyString())-1]].Lock()
57+
return func() {
58+
b.lks[k.KeyString()[len(k.KeyString())-1]].Unlock()
59+
}
60+
}
61+
4862
func (b *arccache) DeleteBlock(k cid.Cid) error {
4963
if has, _, ok := b.queryCache(k); ok && !has {
5064
return nil
5165
}
5266

53-
b.lks[k.Bytes()[len(k.Bytes())-1]].Lock()
54-
defer b.lks[k.Bytes()[len(k.Bytes())-1]].Unlock()
67+
unlock := b.wLock(k)
68+
defer unlock()
5569

5670
b.cache.Remove(k) // Invalidate cache before deleting.
5771
err := b.blockstore.DeleteBlock(k)
@@ -66,6 +80,9 @@ func (b *arccache) Has(k cid.Cid) (bool, error) {
6680
return has, nil
6781
}
6882

83+
unlock := b.rLock(k)
84+
defer unlock()
85+
6986
has, err := b.blockstore.Has(k)
7087
if err != nil {
7188
return false, err
@@ -87,8 +104,8 @@ func (b *arccache) GetSize(k cid.Cid) (int, error) {
87104
// we have it but don't know the size, ask the datastore.
88105
}
89106

90-
b.lks[k.Bytes()[len(k.Bytes())-1]].Lock()
91-
defer b.lks[k.Bytes()[len(k.Bytes())-1]].Unlock()
107+
unlock := b.rLock(k)
108+
defer unlock()
92109

93110
blockSize, err := b.blockstore.GetSize(k)
94111
if err == ErrNotFound {
@@ -121,6 +138,9 @@ func (b *arccache) View(k cid.Cid, callback func([]byte) error) error {
121138
return ErrNotFound
122139
}
123140

141+
unlock := b.rLock(k)
142+
defer unlock()
143+
124144
return b.viewer.View(k, callback)
125145
}
126146

@@ -134,8 +154,8 @@ func (b *arccache) Get(k cid.Cid) (blocks.Block, error) {
134154
return nil, ErrNotFound
135155
}
136156

137-
b.lks[k.Bytes()[len(k.Bytes())-1]].Lock()
138-
defer b.lks[k.Bytes()[len(k.Bytes())-1]].Unlock()
157+
unlock := b.rLock(k)
158+
defer unlock()
139159

140160
bl, err := b.blockstore.Get(k)
141161
if bl == nil && err == ErrNotFound {
@@ -151,8 +171,8 @@ func (b *arccache) Put(bl blocks.Block) error {
151171
return nil
152172
}
153173

154-
b.lks[bl.Cid().Bytes()[len(bl.Cid().Bytes())-1]].Lock()
155-
defer b.lks[bl.Cid().Bytes()[len(bl.Cid().Bytes())-1]].Unlock()
174+
unlock := b.wLock(bl.Cid())
175+
defer unlock()
156176

157177
err := b.blockstore.Put(bl)
158178
if err == nil {
@@ -162,28 +182,30 @@ func (b *arccache) Put(bl blocks.Block) error {
162182
}
163183

164184
func (b *arccache) PutMany(bs []blocks.Block) error {
185+
mxs := [256]*sync.Mutex{}
165186
var good []blocks.Block
166187
for _, block := range bs {
167188
// call put on block if result is inconclusive or we are sure that
168189
// the block isn't in storage
169190
if has, _, ok := b.queryCache(block.Cid()); !ok || (ok && !has) {
170191
good = append(good, block)
171-
b.lks[block.Cid().Bytes()[len(block.Cid().Bytes())-1]].Lock()
192+
mxs[block.Cid().KeyString()[len(block.Cid().KeyString())-1]] = &sync.Mutex{}
172193
}
173194
}
174195

175-
defer func() {
176-
for _, block := range good {
177-
b.lks[block.Cid().Bytes()[len(block.Cid().Bytes())-1]].Unlock()
196+
for _, mx := range mxs {
197+
if mx != nil {
198+
mx.Lock()
178199
}
179-
}()
200+
}
180201

181202
err := b.blockstore.PutMany(good)
182203
if err != nil {
183204
return err
184205
}
185206
for _, block := range good {
186207
b.cacheSize(block.Cid(), len(block.RawData()))
208+
mxs[block.Cid().KeyString()[len(block.Cid().KeyString())-1]].Unlock()
187209
}
188210
return nil
189211
}

0 commit comments

Comments
 (0)