Skip to content

Commit d61ca43

Browse files
authored
CBG-5022: move rev cache locks into defer where possible (#7896)
1 parent 6be8b32 commit d61ca43

File tree

1 file changed

+25
-27
lines changed

1 file changed

+25
-27
lines changed

db/revision_cache_lru.go

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -337,18 +337,33 @@ func (rc *LRURevisionCache) Put(ctx context.Context, docRev DocumentRevision, co
337337

338338
// Upsert a revision in the cache.
339339
func (rc *LRURevisionCache) Upsert(ctx context.Context, docRev DocumentRevision, collectionID uint32) {
340-
var value *revCacheValue
341340
// similar to PUT operation we should have the CV defined by this point (updateHLV is called before calling this)
342341
key := IDandCV{DocID: docRev.DocID, Source: docRev.CV.SourceID, Version: docRev.CV.Value, CollectionID: collectionID}
343342
legacyKey := IDAndRev{DocID: docRev.DocID, RevID: docRev.RevID, CollectionID: collectionID}
344343

344+
numItemsRemoved, value := rc.upsertDocToCache(ctx, key, legacyKey, docRev, collectionID)
345+
if numItemsRemoved > 0 {
346+
rc.cacheNumItems.Add(-numItemsRemoved)
347+
}
348+
349+
docRev.CalculateBytes()
350+
// add new item bytes to overall count
351+
rc.incrRevCacheMemoryUsage(ctx, docRev.MemoryBytes)
352+
value.store(docRev)
353+
354+
// check we aren't over memory capacity, if so perform eviction
355+
rc.revCacheMemoryBasedEviction(ctx)
356+
}
357+
358+
func (rc *LRURevisionCache) upsertDocToCache(ctx context.Context, cvKey IDandCV, legacyKey IDAndRev, docRev DocumentRevision, collectionID uint32) (int64, *revCacheValue) {
345359
rc.lock.Lock()
360+
defer rc.lock.Unlock()
346361

347362
newItem := true
348363
// lookup for element in hlv lookup map, if not found for some reason try rev lookup map
349364
var existingElem *list.Element
350365
var found bool
351-
existingElem, found = rc.hlvCache[key]
366+
existingElem, found = rc.hlvCache[cvKey]
352367
if !found {
353368
existingElem, found = rc.cache[legacyKey]
354369
}
@@ -362,9 +377,9 @@ func (rc *LRURevisionCache) Upsert(ctx context.Context, docRev DocumentRevision,
362377

363378
// Add new value and overwrite existing cache key, pushing to front to maintain order
364379
// also ensure we add to rev id lookup map too
365-
value = &revCacheValue{id: docRev.DocID, cv: *docRev.CV, collectionID: collectionID}
380+
value := &revCacheValue{id: docRev.DocID, cv: *docRev.CV, collectionID: collectionID}
366381
elem := rc.lruList.PushFront(value)
367-
rc.hlvCache[key] = elem
382+
rc.hlvCache[cvKey] = elem
368383
rc.cache[legacyKey] = elem
369384

370385
// only increment if we are inserting new item to cache
@@ -377,18 +392,7 @@ func (rc *LRURevisionCache) Upsert(ctx context.Context, docRev DocumentRevision,
377392
if numBytesEvicted > 0 {
378393
rc._decrRevCacheMemoryUsage(ctx, -numBytesEvicted)
379394
}
380-
rc.lock.Unlock() // release lock after eviction finished
381-
if numItemsRemoved > 0 {
382-
rc.cacheNumItems.Add(-numItemsRemoved)
383-
}
384-
385-
docRev.CalculateBytes()
386-
// add new item bytes to overall count
387-
rc.incrRevCacheMemoryUsage(ctx, docRev.MemoryBytes)
388-
value.store(docRev)
389-
390-
// check we aren't over memory capacity, if so perform eviction
391-
rc.revCacheMemoryBasedEviction(ctx)
395+
return numItemsRemoved, value
392396
}
393397

394398
func (rc *LRURevisionCache) getValue(ctx context.Context, docID, revID string, collectionID uint32, create bool) (value *revCacheValue) {
@@ -398,6 +402,7 @@ func (rc *LRURevisionCache) getValue(ctx context.Context, docID, revID string, c
398402
}
399403
key := IDAndRev{DocID: docID, RevID: revID, CollectionID: collectionID}
400404
rc.lock.Lock()
405+
defer rc.lock.Unlock()
401406
if elem := rc.cache[key]; elem != nil {
402407
rc.lruList.MoveToFront(elem)
403408
value = elem.Value.(*revCacheValue)
@@ -411,14 +416,10 @@ func (rc *LRURevisionCache) getValue(ctx context.Context, docID, revID string, c
411416
if numBytesEvicted > 0 {
412417
rc._decrRevCacheMemoryUsage(ctx, -numBytesEvicted)
413418
}
414-
rc.lock.Unlock() // release lock as eviction is finished
415419
if numItemsRemoved > 0 {
416420
rc.cacheNumItems.Add(-numItemsRemoved)
417421
}
418-
// return early as rev cache mutex has been released at this point
419-
return
420422
}
421-
rc.lock.Unlock()
422423
return
423424
}
424425

@@ -429,6 +430,7 @@ func (rc *LRURevisionCache) getValueByCV(ctx context.Context, docID string, cv *
429430

430431
key := IDandCV{DocID: docID, Source: cv.SourceID, Version: cv.Value, CollectionID: collectionID}
431432
rc.lock.Lock()
433+
defer rc.lock.Unlock()
432434
if elem := rc.hlvCache[key]; elem != nil {
433435
rc.lruList.MoveToFront(elem)
434436
value = elem.Value.(*revCacheValue)
@@ -444,15 +446,11 @@ func (rc *LRURevisionCache) getValueByCV(ctx context.Context, docID string, cv *
444446
if numBytesEvicted > 0 {
445447
rc._decrRevCacheMemoryUsage(ctx, -numBytesEvicted)
446448
}
447-
rc.lock.Unlock() // release lock as eviction is finished
448449

449450
if numItemsRemoved > 0 {
450451
rc.cacheNumItems.Add(-numItemsRemoved)
451452
}
452-
// return early as rev cache mutex has been released at this point
453-
return
454453
}
455-
rc.lock.Unlock()
456454
return
457455
}
458456

@@ -706,6 +704,7 @@ func (value *revCacheValue) load(ctx context.Context, backingStore RevisionCache
706704
value.lock.RUnlock()
707705

708706
value.lock.Lock()
707+
defer value.lock.Unlock()
709708
// Check if the value was loaded while we waited for the lock - if so, return.
710709
if value.bodyBytes != nil || value.err != nil {
711710
cacheHit = true
@@ -754,7 +753,6 @@ func (value *revCacheValue) load(ctx context.Context, backingStore RevisionCache
754753
docRev.CalculateBytes()
755754
value.itemBytes.Store(docRev.MemoryBytes)
756755
}
757-
value.lock.Unlock()
758756

759757
return docRev, cacheHit, err
760758
}
@@ -799,6 +797,7 @@ func (value *revCacheValue) loadForDoc(ctx context.Context, backingStore Revisio
799797
value.lock.RUnlock()
800798

801799
value.lock.Lock()
800+
defer value.lock.Unlock()
802801
// Check if the value was loaded while we waited for the lock - if so, return.
803802
if value.bodyBytes != nil || value.err != nil {
804803
cacheHit = true
@@ -828,13 +827,13 @@ func (value *revCacheValue) loadForDoc(ctx context.Context, backingStore Revisio
828827
docRev.CalculateBytes()
829828
value.itemBytes.Store(docRev.MemoryBytes)
830829
}
831-
value.lock.Unlock()
832830
return docRev, cacheHit, err
833831
}
834832

835833
// Stores a body etc. into a revCacheValue if there isn't one already.
836834
func (value *revCacheValue) store(docRev DocumentRevision) {
837835
value.lock.Lock()
836+
defer value.lock.Unlock()
838837
if value.bodyBytes == nil {
839838
value.revID = docRev.RevID
840839
value.id = docRev.DocID
@@ -848,7 +847,6 @@ func (value *revCacheValue) store(docRev DocumentRevision) {
848847
value.itemBytes.Store(docRev.MemoryBytes)
849848
value.hlvHistory = docRev.HlvHistory
850849
}
851-
value.lock.Unlock()
852850
value.canEvict.Store(true) // now we have stored the doc revision in the cache, we can allow eviction
853851
}
854852

0 commit comments

Comments
 (0)