@@ -337,18 +337,33 @@ func (rc *LRURevisionCache) Put(ctx context.Context, docRev DocumentRevision, co
337337
338338// Upsert a revision in the cache.
339339func (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
394398func (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.
836834func (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