Aleksey Plekhanov created IGNITE-25172:
------------------------------------------

             Summary: Expired locked tx cache entries are not deleted
                 Key: IGNITE-25172
                 URL: https://issues.apache.org/jira/browse/IGNITE-25172
             Project: Ignite
          Issue Type: Bug
            Reporter: Aleksey Plekhanov


For transactional caches expired entries are not deleted if they are locked and 
there was attempt to expire.

Reproducer:
{code:java}
@Test
public void testEntriesLeakTx() throws Exception {
    IgniteEx srv = startGrid();

    IgniteCache<Object, Object> cache = srv.getOrCreateCache(new 
CacheConfiguration<>(DEFAULT_CACHE_NAME)
        .setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL))
        .withExpiryPolicy(new CreatedExpiryPolicy(new 
Duration(TimeUnit.MILLISECONDS, 100)));

    Map<Integer, Integer> map = new TreeMap<>();

    for (int i = 0; i < 1_000; i++)
        map.put(i, i);

    cache.putAll(map);

    try (Transaction tx = 
srv.transactions().txStart(TransactionConcurrency.PESSIMISTIC, 
TransactionIsolation.REPEATABLE_READ)) {
        cache.getAll(map.keySet());

        doSleep(1_000);

        tx.commit();
    }

    assertEquals(0, cache.size());
} {code}
The same problem also occurs when CDC is trying to insert almost expired 
entries to a transactional cache (CDC uses putAllConflict method):
{code:java}
@Test
public void testEntriesLeakCdc() throws Exception {
    IgniteEx srv = startGrid();

    IgniteCache<Object, Object> cache = srv.getOrCreateCache(new 
CacheConfiguration<>(DEFAULT_CACHE_NAME)
        .setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL));

    IgniteInternalCache<Object, Object> cachex = srv.cachex(DEFAULT_CACHE_NAME);

    GridCacheVersion ver = new GridCacheVersion(1, 1, 1, 2);
    CacheObjectImpl val = new CacheObjectImpl(1, null);

    Map<KeyCacheObject, GridCacheDrInfo> map = new HashMap<>();

    for (int i = 0; i < 100_000; i++)
        map.put(
            new KeyCacheObjectImpl(i, null, -1),
            new GridCacheDrExpirationInfo(val, ver, 1, CU.toExpireTime(1)));

    cachex.putAllConflict(map);

    assertTrue(GridTestUtils.waitForCondition(() -> cache.size() == 0, 
10_000L));
} {code}
There is locks check in \{{GridCacheMapEntry#onExpired}} method:
{code:java}
if (mvccExtras() != null)
    return false; {code}
Before actual entry remove. Due to this check entry stays in cache, while 
{{PendingTree}} entry already removed.



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

Reply via email to