[ 
https://issues.apache.org/jira/browse/HBASE-30285?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

ASF GitHub Bot updated HBASE-30285:
-----------------------------------
    Labels: pull-request-available  (was: )

> BucketCache shutdown/disable does not release backingMap-owned BucketEntry 
> references
> -------------------------------------------------------------------------------------
>
>                 Key: HBASE-30285
>                 URL: https://issues.apache.org/jira/browse/HBASE-30285
>             Project: HBase
>          Issue Type: Bug
>            Reporter: Minwoo Kang
>            Assignee: Minwoo Kang
>            Priority: Minor
>              Labels: pull-request-available
>
> h2. Description
> {{BucketCache}} does not release the reference owned by {{backingMap}} when 
> the cache is shut down or disabled.
> A newly created {{BucketEntry}} has an initial reference count of 1. This 
> reference is owned by {{BucketCache.backingMap}}.
> For shared-memory IO engines, {{BucketCache.getBlock()}} retains the same 
> {{RefCnt}} before returning a cached block. After the caller releases the 
> returned block, the backing map reference remains with a count of 1.
> Normal eviction removes the map entry under the offset write lock and calls 
> {{blockEvicted()}}. {{blockEvicted()}} calls {{BucketEntry.markAsEvicted()}}, 
> which releases the backing map reference.
> The non-persistent path in {{BucketCache.disableCache()}} instead calls 
> {{backingMap.clear()}} directly. This removes the map references without 
> calling {{markAsEvicted()}}. Each affected {{BucketEntry}} therefore retains 
> a reference count of 1.
> The persistent shutdown path needs the backing map for serialization, but it 
> also does not release the owner references after serialization completes
> h2. Reproduction
> Add the following deterministic test to 
> {{hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCacheRefCnt.java}}.
> {code:java}
> @Test
> public void testShutdownReleasesBackingMapReference() throws Exception {
>   ByteBuffAllocator alloc = 
> ByteBuffAllocator.create(HBaseConfiguration.create(), true);
>   HFileBlock blockToCache = createBlock(200, 1020, alloc);
>   HFileBlock blockFromCache = null;
>   try {
>     cache = create(1, 1000);
>     BlockCacheKey key = createKey("testShutdownReleasesBackingMapReference", 
> 200);
>     cache.cacheBlock(key, blockToCache);
>     waitUntilFlushedToCache(cache, key);
>     blockFromCache = (HFileBlock) cache.getBlock(key, false, false, false);
>     assertNotNull(blockFromCache);
>     assertEquals(2, blockFromCache.refCnt());
>     blockFromCache.release();
>     assertEquals(1, blockFromCache.refCnt());
>     cache.shutdown();
>     cache = null;
>     assertEquals(0, blockFromCache.refCnt(),
>       "BucketCache.shutdown must release the backingMap reference for every 
> BucketEntry");
>   } finally {
>     if (cache != null) {
>       cache.shutdown();
>     }
>     if (blockFromCache != null) {
>       while (blockFromCache.refCnt() > 0) {
>         blockFromCache.release();
>       }
>     }
>     while (blockToCache.refCnt() > 0) {
>       blockToCache.release();
>     }
>     alloc.clean();
>   }
> }
> {code}
> h2. Expected behavior
> {{BucketCache}} should release each reference owned by {{backingMap}} exactly 
> once when the entry is discarded.
> References held by in-flight callers must remain valid until those callers 
> release them.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to