Search in sources :

Example 66 with GridDhtLocalPartition

use of org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition in project ignite by apache.

the class CacheDeferredDeleteQueueTest method testQueue.

/**
 * @param atomicityMode Cache atomicity mode.
 * @param nearCache {@code True} if need create near cache.
 *
 * @throws Exception If failed.
 */
private void testQueue(CacheAtomicityMode atomicityMode, boolean nearCache) throws Exception {
    CacheConfiguration<Integer, Integer> ccfg = new CacheConfiguration<>(DEFAULT_CACHE_NAME);
    ccfg.setCacheMode(PARTITIONED);
    ccfg.setAtomicityMode(atomicityMode);
    ccfg.setWriteSynchronizationMode(FULL_SYNC);
    ccfg.setBackups(1);
    if (nearCache)
        ccfg.setNearConfiguration(new NearCacheConfiguration<Integer, Integer>());
    IgniteCache<Integer, Integer> cache = ignite(0).createCache(ccfg);
    try {
        final int KEYS = cache.getConfiguration(CacheConfiguration.class).getAffinity().partitions() * 3;
        for (int i = 0; i < KEYS; i++) cache.put(i, i);
        for (int i = 0; i < KEYS; i++) cache.remove(i);
        boolean wait = GridTestUtils.waitForCondition(new GridAbsPredicate() {

            @Override
            public boolean apply() {
                for (int i = 0; i < NODES; i++) {
                    final GridDhtPartitionTopology top = ((IgniteKernal) ignite(i)).context().cache().cache(DEFAULT_CACHE_NAME).context().topology();
                    for (GridDhtLocalPartition p : top.currentLocalPartitions()) {
                        Collection<Object> rmvQueue = GridTestUtils.getFieldValue(p, "rmvQueue");
                        if (!rmvQueue.isEmpty() || p.dataStore().fullSize() != 0)
                            return false;
                    }
                }
                return true;
            }
        }, 5000);
        assertTrue("Failed to wait for rmvQueue cleanup.", wait);
    } finally {
        ignite(0).destroyCache(ccfg.getName());
    }
}
Also used : GridAbsPredicate(org.apache.ignite.internal.util.lang.GridAbsPredicate) GridDhtPartitionTopology(org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionTopology) Collection(java.util.Collection) GridDhtLocalPartition(org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition) NearCacheConfiguration(org.apache.ignite.configuration.NearCacheConfiguration) CacheConfiguration(org.apache.ignite.configuration.CacheConfiguration) NearCacheConfiguration(org.apache.ignite.configuration.NearCacheConfiguration)

Example 67 with GridDhtLocalPartition

use of org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition in project ignite by apache.

the class IgniteCacheGroupsTest method testRestartsAndCacheCreateDestroy.

/**
 * @throws Exception If failed.
 */
@Test
public void testRestartsAndCacheCreateDestroy() throws Exception {
    final int SRVS = 5;
    startGrids(SRVS);
    final Ignite clientNode = startClientGrid(SRVS);
    final int CACHES = SF.applyLB(10, 2);
    final AtomicReferenceArray<IgniteCache> caches = new AtomicReferenceArray<>(CACHES);
    for (int i = 0; i < CACHES; i++) {
        CacheAtomicityMode atomicityMode = i % 2 == 0 ? ATOMIC : TRANSACTIONAL;
        caches.set(i, clientNode.createCache(cacheConfiguration(GROUP1, "c" + i, PARTITIONED, atomicityMode, 0, false)));
    }
    final AtomicBoolean stop = new AtomicBoolean();
    final AtomicInteger cacheCntr = new AtomicInteger();
    try {
        final int ITERATIONS_COUNT = SF.applyLB(10, 1);
        for (int i = 0; i < ITERATIONS_COUNT; i++) {
            stop.set(false);
            final AtomicReference<Exception> err = new AtomicReference<>();
            log.info("Iteration: " + i);
            IgniteInternalFuture<?> restartFut = GridTestUtils.runAsync(new Runnable() {

                @Override
                public void run() {
                    try {
                        ThreadLocalRandom rnd = ThreadLocalRandom.current();
                        while (!stop.get()) {
                            int node = rnd.nextInt(SRVS);
                            log.info("Stop node: " + node);
                            stopGrid(node);
                            U.sleep(500);
                            log.info("Start node: " + node);
                            startGrid(node);
                            try {
                                if (rnd.nextBoolean())
                                    awaitPartitionMapExchange();
                            } catch (Exception ignore) {
                            // No-op.
                            }
                        }
                    } catch (Exception e) {
                        log.error("Unexpected error: " + e, e);
                        err.set(e);
                        stop.set(true);
                    }
                }
            });
            IgniteInternalFuture<?> cacheFut = GridTestUtils.runAsync(new Runnable() {

                @Override
                public void run() {
                    try {
                        ThreadLocalRandom rnd = ThreadLocalRandom.current();
                        while (!stop.get()) {
                            int idx = rnd.nextInt(CACHES);
                            IgniteCache cache = caches.get(idx);
                            if (cache != null && caches.compareAndSet(idx, cache, null)) {
                                log.info("Destroy cache: " + cache.getName());
                                clientNode.destroyCache(cache.getName());
                                CacheAtomicityMode atomicityMode = rnd.nextBoolean() ? ATOMIC : TRANSACTIONAL;
                                String name = "newName-" + cacheCntr.incrementAndGet();
                                cache = clientNode.createCache(cacheConfiguration(GROUP1, name, PARTITIONED, atomicityMode, 0, false));
                                caches.set(idx, cache);
                            }
                        }
                    } catch (Exception e) {
                        log.error("Unexpected error: " + e, e);
                        err.set(e);
                        stop.set(true);
                    }
                }
            });
            IgniteInternalFuture opFut = GridTestUtils.runMultiThreadedAsync(new Runnable() {

                @Override
                public void run() {
                    ThreadLocalRandom rnd = ThreadLocalRandom.current();
                    while (!stop.get()) {
                        try {
                            int idx = rnd.nextInt(CACHES);
                            IgniteCache cache = caches.get(idx);
                            if (cache != null && caches.compareAndSet(idx, cache, null)) {
                                try {
                                    for (int i = 0; i < 10; i++) cacheOperation(rnd, cache);
                                } catch (Exception e) {
                                    if (X.hasCause(e, CacheStoppedException.class) || (X.hasCause(e, CacheInvalidStateException.class) && X.hasCause(e, TransactionRollbackException.class))) {
                                        // if a node was stopped during transaction.
                                        continue;
                                    }
                                    throw e;
                                } finally {
                                    caches.set(idx, cache);
                                }
                            }
                        } catch (Exception e) {
                            err.set(e);
                            log.error("Unexpected error: " + e, e);
                            stop.set(true);
                        }
                    }
                }
            }, 8, "op-thread");
            Thread.sleep(SF.applyLB(10_000, 1_000));
            stop.set(true);
            restartFut.get();
            cacheFut.get();
            opFut.get();
            assertNull("Unexpected error during test, see log for details", err.get());
            awaitPartitionMapExchange();
            Set<Integer> cacheIds = new HashSet<>();
            for (int c = 0; c < CACHES; c++) {
                IgniteCache cache = caches.get(c);
                assertNotNull(cache);
                assertTrue(cacheIds.add(CU.cacheId(cache.getName())));
            }
            for (int n = 0; n < SRVS; n++) {
                CacheGroupContext grp = cacheGroup(ignite(n), GROUP1);
                assertNotNull(grp);
                for (GridDhtLocalPartition part : grp.topology().currentLocalPartitions()) {
                    IntMap<Object> cachesMap = GridTestUtils.getFieldValue(part, "cacheMaps");
                    assertTrue(cachesMap.size() <= cacheIds.size());
                    cachesMap.forEach((cacheId, v) -> assertTrue(cachesMap.containsKey(cacheId)));
                }
            }
        }
    } finally {
        stop.set(true);
    }
}
Also used : TransactionRollbackException(org.apache.ignite.transactions.TransactionRollbackException) IgniteInternalFuture(org.apache.ignite.internal.IgniteInternalFuture) AtomicReferenceArray(java.util.concurrent.atomic.AtomicReferenceArray) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) Ignite(org.apache.ignite.Ignite) GridDhtLocalPartition(org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition) LinkedHashSet(java.util.LinkedHashSet) HashSet(java.util.HashSet) IgniteCache(org.apache.ignite.IgniteCache) AtomicReference(java.util.concurrent.atomic.AtomicReference) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) EntryProcessorException(javax.cache.processor.EntryProcessorException) CacheLoaderException(javax.cache.integration.CacheLoaderException) TransactionRollbackException(org.apache.ignite.transactions.TransactionRollbackException) CacheWriterException(javax.cache.integration.CacheWriterException) CacheExistsException(org.apache.ignite.cache.CacheExistsException) CacheException(javax.cache.CacheException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) CacheAtomicityMode(org.apache.ignite.cache.CacheAtomicityMode) BinaryObject(org.apache.ignite.binary.BinaryObject) Test(org.junit.Test) GridCommonAbstractTest(org.apache.ignite.testframework.junits.common.GridCommonAbstractTest)

Example 68 with GridDhtLocalPartition

use of org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition in project ignite by apache.

the class GridCachePartitionedUnloadEventsSelfTest method checkPartitionUnloadEvents.

/**
 * @param evts Events.
 * @param g Grid.
 * @param parts Parts.
 */
private void checkPartitionUnloadEvents(Collection<Event> evts, Ignite g, Collection<GridDhtLocalPartition> parts) {
    assertEquals(parts.size(), evts.size());
    for (Event evt : evts) {
        CacheRebalancingEvent unloadEvt = (CacheRebalancingEvent) evt;
        final int part = unloadEvt.partition();
        assertNotNull("Unexpected partition: " + part, F.find(parts, null, new IgnitePredicate<GridDhtLocalPartition>() {

            @Override
            public boolean apply(GridDhtLocalPartition e) {
                return e.id() == part;
            }
        }));
        assertEquals(g.cache(DEFAULT_CACHE_NAME).getName(), unloadEvt.cacheName());
        assertEquals(g.cluster().localNode().id(), unloadEvt.node().id());
    }
}
Also used : IgnitePredicate(org.apache.ignite.lang.IgnitePredicate) CacheEvent(org.apache.ignite.events.CacheEvent) Event(org.apache.ignite.events.Event) CacheRebalancingEvent(org.apache.ignite.events.CacheRebalancingEvent) GridDhtLocalPartition(org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition) CacheRebalancingEvent(org.apache.ignite.events.CacheRebalancingEvent)

Example 69 with GridDhtLocalPartition

use of org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition in project ignite by apache.

the class IgnitePdsCacheEntriesExpirationTest method testDeadlockBetweenCachePutAndEntryExpiration.

/**
 * Verifies scenario of a deadlock between thread, modifying a cache entry (acquires cp read lock and entry lock),
 * ttl thread, expiring the entry (acquires cp read lock and entry lock) and checkpoint thread (acquires cp write
 * lock).
 *
 * Checkpoint thread in not used but emulated by the test to avoid test hang (interruptible API for acquiring write
 * lock is used).
 *
 * For more details see <a href="https://ggsystems.atlassian.net/browse/GG-23135">GG-23135</a>.
 *
 * <p> <strong>Important note</strong> Implementation of this test relies heavily on structure of existing code in
 * {@link GridCacheOffheapManager.GridCacheDataStore#purgeExpiredInternal(GridCacheContext, IgniteInClosure2X, int)}
 * and {@link GridCacheMapEntry#onExpired(CacheObject, GridCacheVersion)} methods.
 *
 * Any changes to those methods could break logic inside the test so if new failures of the test occure test code
 * itself may require refactoring. </p>
 *
 * @throws Exception If failed.
 */
@Test
public void testDeadlockBetweenCachePutAndEntryExpiration() throws Exception {
    AtomicBoolean timeoutReached = new AtomicBoolean(false);
    AtomicBoolean cpWriteLocked = new AtomicBoolean(false);
    AtomicInteger partId = new AtomicInteger();
    CountDownLatch ttlLatch = new CountDownLatch(2);
    IgniteEx srv0 = startGrids(2);
    srv0.cluster().active(true);
    awaitPartitionMapExchange();
    srv0.getOrCreateCache(DEFAULT_CACHE_NAME);
    GridDhtPartitionTopologyImpl top = (GridDhtPartitionTopologyImpl) srv0.cachex(DEFAULT_CACHE_NAME).context().topology();
    top.partitionFactory((ctx, grp, id, recovery) -> {
        partId.set(id);
        return new GridDhtLocalPartition(ctx, grp, id, recovery) {

            /**
             * This method is modified to bring threads in deadlock situation.
             * Idea is the following: updater thread (see code below) on its way to
             * {@link GridCacheMapEntry#onExpired(CacheObject, GridCacheVersion)} call stops here
             * (already having entry lock acquired) and waits until checkpoint write lock is acquired
             * by another special thread imulating checkpointer thread (cp-write-lock-holder, see code below).
             * After that it enables ttl-cleanup-worker thread to proceed
             * (by counting down ttLatch, see next overridden method) and reproduce deadlock scenario.
             */
            @Override
            public IgniteCacheOffheapManager.CacheDataStore dataStore() {
                Thread t = Thread.currentThread();
                String tName = t.getName();
                if (tName == null || !tName.contains("updater"))
                    return super.dataStore();
                boolean unswapFoundInST = false;
                for (StackTraceElement e : t.getStackTrace()) {
                    if (e.getMethodName().contains("unswap")) {
                        unswapFoundInST = true;
                        break;
                    }
                }
                if (!unswapFoundInST)
                    return super.dataStore();
                while (!cpWriteLocked.get()) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException ignored) {
                        log.warning(">>> Thread caught InterruptedException while waiting " + "for cp write lock to be locked");
                    }
                }
                ttlLatch.countDown();
                return super.dataStore();
            }

            /**
             * This method is modified to bring threads in deadlock situation.
             * Idea is the following: internal ttl-cleanup-worker thread wakes up to cleanup expired entries,
             * reaches this method after calling purgeExpiredInternal (thus having checkpoint readlock acquired)
             * and stops on ttlLatch until updater thread comes in, acquires entry lock and gets stuck
             * on acquiring cp read lock
             * (because of special cp-write-lock-holder thread already holding cp write lock).
             *
             * So situation of three threads stuck in deadlock is reproduced.
             */
            @Override
            public boolean reserve() {
                Thread t = Thread.currentThread();
                String tName = t.getName();
                if (tName == null || !tName.contains("ttl-cleanup-worker"))
                    return super.reserve();
                boolean purgeExpiredFoundInST = false;
                for (StackTraceElement e : t.getStackTrace()) {
                    if (e.getMethodName().contains("purgeExpiredInternal")) {
                        purgeExpiredFoundInST = true;
                        break;
                    }
                }
                if (!purgeExpiredFoundInST)
                    return super.reserve();
                ttlLatch.countDown();
                try {
                    ttlLatch.await();
                } catch (InterruptedException ignored) {
                    log.warning(">>> Thread caught InterruptedException while waiting for ttl latch" + " to be released by updater thread");
                }
                return super.reserve();
            }
        };
    });
    stopGrid(1);
    // change BLT to force new partition creation with modified GridDhtLocalPartition class
    srv0.cluster().setBaselineTopology(srv0.cluster().topologyVersion());
    Thread.sleep(500);
    IgniteCache<Object, Object> cache = srv0.getOrCreateCache(DEFAULT_CACHE_NAME);
    GridCacheDatabaseSharedManager db = (GridCacheDatabaseSharedManager) srv0.context().cache().context().database();
    CheckpointReadWriteLock checkpointReadWriteLock = U.field(db.checkpointManager.checkpointTimeoutLock(), "checkpointReadWriteLock");
    ReentrantReadWriteLockWithTracking rwLock = U.field(checkpointReadWriteLock, "checkpointLock");
    int key = 0;
    while (true) {
        if (srv0.affinity(DEFAULT_CACHE_NAME).partition(key) != partId.get())
            key++;
        else
            break;
    }
    cache.put(key, 1);
    int finalKey = key;
    IgniteInternalFuture updateFut = GridTestUtils.runAsync(() -> {
        log.info(">>> Updater thread has started, updating key " + finalKey);
        int i = 10;
        while (!timeoutReached.get()) {
            cache.put(finalKey, i++);
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                log.warning(">>> Updater thread sleep was interrupted");
            }
        }
    }, "updater-thread");
    IgniteInternalFuture writeLockHolderFut = GridTestUtils.runAsync(() -> {
        while (ttlLatch.getCount() != 1) {
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                log.warning(">>> Write lock holder thread sleep was interrupted");
                break;
            }
        }
        try {
            cpWriteLocked.set(true);
            rwLock.writeLock().lockInterruptibly();
            ttlLatch.await();
        } catch (InterruptedException e) {
            log.warning(">>> Write lock holder thread was interrupted while obtaining write lock.");
        } finally {
            rwLock.writeLock().unlock();
        }
    }, "cp-write-lock-holder");
    GridTestUtils.runAsync(() -> {
        long start = System.currentTimeMillis();
        while (System.currentTimeMillis() - start < TIMEOUT) doSleep(1_000);
        timeoutReached.set(true);
    });
    try {
        updateFut.get(TIMEOUT * 2);
    } catch (IgniteFutureTimeoutCheckedException ignored) {
        fail("Failed to wait for futures for doubled timeout");
    } finally {
        while (ttlLatch.getCount() > 0) ttlLatch.countDown();
        writeLockHolderFut.cancel();
        updateFut.cancel();
    }
}
Also used : CheckpointReadWriteLock(org.apache.ignite.internal.processors.cache.persistence.checkpoint.CheckpointReadWriteLock) CountDownLatch(java.util.concurrent.CountDownLatch) ReentrantReadWriteLockWithTracking(org.apache.ignite.internal.util.ReentrantReadWriteLockWithTracking) IgniteInternalFuture(org.apache.ignite.internal.IgniteInternalFuture) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) IgniteCacheOffheapManager(org.apache.ignite.internal.processors.cache.IgniteCacheOffheapManager) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) IgniteEx(org.apache.ignite.internal.IgniteEx) IgniteFutureTimeoutCheckedException(org.apache.ignite.internal.IgniteFutureTimeoutCheckedException) CacheObject(org.apache.ignite.internal.processors.cache.CacheObject) GridDhtLocalPartition(org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition) GridDhtPartitionTopologyImpl(org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionTopologyImpl) GridCommonAbstractTest(org.apache.ignite.testframework.junits.common.GridCommonAbstractTest) Test(org.junit.Test)

Example 70 with GridDhtLocalPartition

use of org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition in project ignite by apache.

the class IgniteAbsentEvictionNodeOutOfBaselineTest method testPartitionsRemovedIfJoiningNodeNotInBaseline.

/**
 * Removed partitions if node is out of baseline.
 */
@Test
public void testPartitionsRemovedIfJoiningNodeNotInBaseline() throws Exception {
    // given: start 3 nodes with data
    Ignite ignite0 = startGrids(3);
    ignite0.cluster().baselineAutoAdjustEnabled(false);
    ignite0.cluster().active(true);
    IgniteCache<Object, Object> cache = ignite0.getOrCreateCache(TEST_CACHE_NAME);
    for (int i = 0; i < 100; i++) cache.put(i, i);
    // when: stop one node and reset baseline topology
    stopGrid(2);
    resetBaselineTopology();
    ignite0.resetLostPartitions(Collections.singleton(TEST_CACHE_NAME));
    awaitPartitionMapExchange();
    for (int i = 0; i < 200; i++) cache.put(i, i);
    // then: after returning stopped node to grid its partitions should be removed
    IgniteEx ignite2 = startGrid(2);
    List<GridDhtLocalPartition> partitions = ignite2.cachex(TEST_CACHE_NAME).context().topology().localPartitions();
    assertTrue("Should be empty : " + partitions, partitions.isEmpty());
}
Also used : IgniteEx(org.apache.ignite.internal.IgniteEx) Ignite(org.apache.ignite.Ignite) GridDhtLocalPartition(org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition) GridCommonAbstractTest(org.apache.ignite.testframework.junits.common.GridCommonAbstractTest) Test(org.junit.Test)

Aggregations

GridDhtLocalPartition (org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition)95 GridDhtPartitionTopology (org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionTopology)21 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)19 IgniteEx (org.apache.ignite.internal.IgniteEx)19 CacheGroupContext (org.apache.ignite.internal.processors.cache.CacheGroupContext)19 ArrayList (java.util.ArrayList)18 Map (java.util.Map)18 Test (org.junit.Test)18 AffinityTopologyVersion (org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion)16 GridCommonAbstractTest (org.apache.ignite.testframework.junits.common.GridCommonAbstractTest)16 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)15 ClusterNode (org.apache.ignite.cluster.ClusterNode)15 GridCacheContext (org.apache.ignite.internal.processors.cache.GridCacheContext)15 HashMap (java.util.HashMap)14 HashSet (java.util.HashSet)13 AtomicLong (java.util.concurrent.atomic.AtomicLong)13 CacheDataRow (org.apache.ignite.internal.processors.cache.persistence.CacheDataRow)13 Ignite (org.apache.ignite.Ignite)12 KeyCacheObject (org.apache.ignite.internal.processors.cache.KeyCacheObject)12 IgniteException (org.apache.ignite.IgniteException)11