@Override public void waitForPairing(PairingListener listener) { Preconditions.checkNotNull(listener); logger.info("Waiting for test notification to pair device"); pairingListener = listener; waitingForPairing.set(true); }
public EmReactor() { Timers = new TreeMap<Long, ArrayList<Long>>(); Connections = new HashMap<Long, EventableChannel>(); Acceptors = new HashMap<Long, ServerSocketChannel>(); NewConnections = new ArrayList<Long>(); UnboundConnections = new ArrayList<Long>(); DetachedConnections = new ArrayList<EventableSocketChannel>(); BindingIndex = 0; loopBreaker = new AtomicBoolean(); loopBreaker.set(false); myReadBuffer = ByteBuffer.allocate( 32 * 1024); // don't use a direct buffer. Ruby doesn't seem to like them. timerQuantum = 98; }
private <E> Predicate<E> createJoinPredicate(final AtomicBoolean more) { if (column == null && this.nodes == null) return null; final EntityCache<E> joinCache = this.joinEntity.getCache(); Predicate<E> filter = createElementPredicate(joinCache, true); if (this.nodes != null) { for (FilterNode node : this.nodes) { if (((FilterJoinNode) node).joinClass != this.joinClass) { more.set(true); continue; } Predicate<E> f = ((FilterJoinNode) node).createJoinPredicate(more); if (f == null) continue; final Predicate<E> one = filter; final Predicate<E> two = f; filter = (filter == null) ? f : (or ? new Predicate<E>() { @Override public boolean test(E t) { return one.test(t) || two.test(t); } @Override public String toString() { return "(" + one + " OR " + two + ")"; } } : new Predicate<E>() { @Override public boolean test(E t) { return one.test(t) && two.test(t); } @Override public String toString() { return "(" + one + " AND " + two + ")"; } }); } } return filter; }
/** * Starts activity. * * @throws IgniteInterruptedCheckedException If interrupted. */ public void init() throws IgniteInterruptedCheckedException { if (isDone()) return; if (init.compareAndSet(false, true)) { if (isDone()) return; try { // Wait for event to occur to make sure that discovery // will return corresponding nodes. U.await(evtLatch); assert discoEvt != null : this; assert !dummy && !forcePreload : this; ClusterNode oldest = CU.oldestAliveCacheServerNode(cctx, exchId.topologyVersion()); oldestNode.set(oldest); startCaches(); // True if client node joined or failed. boolean clientNodeEvt; if (F.isEmpty(reqs)) { int type = discoEvt.type(); assert type == EVT_NODE_JOINED || type == EVT_NODE_LEFT || type == EVT_NODE_FAILED : discoEvt; clientNodeEvt = CU.clientNode(discoEvt.eventNode()); } else { assert discoEvt.type() == EVT_DISCOVERY_CUSTOM_EVT : discoEvt; boolean clientOnlyStart = true; for (DynamicCacheChangeRequest req : reqs) { if (!req.clientStartOnly()) { clientOnlyStart = false; break; } } clientNodeEvt = clientOnlyStart; } if (clientNodeEvt) { ClusterNode node = discoEvt.eventNode(); // Client need to initialize affinity for local join event or for stated client caches. if (!node.isLocal()) { for (GridCacheContext cacheCtx : cctx.cacheContexts()) { if (cacheCtx.isLocal()) continue; GridDhtPartitionTopology top = cacheCtx.topology(); top.updateTopologyVersion(exchId, this, -1, stopping(cacheCtx.cacheId())); if (cacheCtx.affinity().affinityTopologyVersion() == AffinityTopologyVersion.NONE) { initTopology(cacheCtx); top.beforeExchange(this); } else cacheCtx.affinity().clientEventTopologyChange(discoEvt, exchId.topologyVersion()); } if (exchId.isLeft()) cctx.mvcc().removeExplicitNodeLocks(exchId.nodeId(), exchId.topologyVersion()); onDone(exchId.topologyVersion()); skipPreload = cctx.kernalContext().clientNode(); return; } } if (cctx.kernalContext().clientNode()) { skipPreload = true; for (GridCacheContext cacheCtx : cctx.cacheContexts()) { if (cacheCtx.isLocal()) continue; GridDhtPartitionTopology top = cacheCtx.topology(); top.updateTopologyVersion(exchId, this, -1, stopping(cacheCtx.cacheId())); } for (GridCacheContext cacheCtx : cctx.cacheContexts()) { if (cacheCtx.isLocal()) continue; initTopology(cacheCtx); } if (oldestNode.get() != null) { rmtNodes = new ConcurrentLinkedQueue<>( CU.aliveRemoteServerNodesWithCaches(cctx, exchId.topologyVersion())); rmtIds = Collections.unmodifiableSet(new HashSet<>(F.nodeIds(rmtNodes))); ready.set(true); initFut.onDone(true); if (log.isDebugEnabled()) log.debug("Initialized future: " + this); sendPartitions(); } else onDone(exchId.topologyVersion()); return; } assert oldestNode.get() != null; for (GridCacheContext cacheCtx : cctx.cacheContexts()) { if (isCacheAdded(cacheCtx.cacheId(), exchId.topologyVersion())) { if (cacheCtx .discovery() .cacheAffinityNodes(cacheCtx.name(), topologyVersion()) .isEmpty()) U.quietAndWarn(log, "No server nodes found for cache client: " + cacheCtx.namex()); } cacheCtx.preloader().onExchangeFutureAdded(); } List<String> cachesWithoutNodes = null; if (exchId.isLeft()) { for (String name : cctx.cache().cacheNames()) { if (cctx.discovery().cacheAffinityNodes(name, topologyVersion()).isEmpty()) { if (cachesWithoutNodes == null) cachesWithoutNodes = new ArrayList<>(); cachesWithoutNodes.add(name); // Fire event even if there is no client cache started. if (cctx.gridEvents().isRecordable(EventType.EVT_CACHE_NODES_LEFT)) { Event evt = new CacheEvent( name, cctx.localNode(), cctx.localNode(), "All server nodes have left the cluster.", EventType.EVT_CACHE_NODES_LEFT, 0, false, null, null, null, null, false, null, false, null, null, null); cctx.gridEvents().record(evt); } } } } if (cachesWithoutNodes != null) { StringBuilder sb = new StringBuilder( "All server nodes for the following caches have left the cluster: "); for (int i = 0; i < cachesWithoutNodes.size(); i++) { String cache = cachesWithoutNodes.get(i); sb.append('\'').append(cache).append('\''); if (i != cachesWithoutNodes.size() - 1) sb.append(", "); } U.quietAndWarn(log, sb.toString()); U.quietAndWarn(log, "Must have server nodes for caches to operate."); } assert discoEvt != null; assert exchId.nodeId().equals(discoEvt.eventNode().id()); for (GridCacheContext cacheCtx : cctx.cacheContexts()) { GridClientPartitionTopology clientTop = cctx.exchange().clearClientTopology(cacheCtx.cacheId()); long updSeq = clientTop == null ? -1 : clientTop.lastUpdateSequence(); // Update before waiting for locks. if (!cacheCtx.isLocal()) cacheCtx .topology() .updateTopologyVersion(exchId, this, updSeq, stopping(cacheCtx.cacheId())); } // Grab all alive remote nodes with order of equal or less than last joined node. rmtNodes = new ConcurrentLinkedQueue<>( CU.aliveRemoteServerNodesWithCaches(cctx, exchId.topologyVersion())); rmtIds = Collections.unmodifiableSet(new HashSet<>(F.nodeIds(rmtNodes))); for (Map.Entry<UUID, GridDhtPartitionsSingleMessage> m : singleMsgs.entrySet()) // If received any messages, process them. onReceive(m.getKey(), m.getValue()); for (Map.Entry<UUID, GridDhtPartitionsFullMessage> m : fullMsgs.entrySet()) // If received any messages, process them. onReceive(m.getKey(), m.getValue()); AffinityTopologyVersion topVer = exchId.topologyVersion(); for (GridCacheContext cacheCtx : cctx.cacheContexts()) { if (cacheCtx.isLocal()) continue; // Must initialize topology after we get discovery event. initTopology(cacheCtx); cacheCtx.preloader().updateLastExchangeFuture(this); } IgniteInternalFuture<?> partReleaseFut = cctx.partitionReleaseFuture(topVer); // Assign to class variable so it will be included into toString() method. this.partReleaseFut = partReleaseFut; if (log.isDebugEnabled()) log.debug("Before waiting for partition release future: " + this); while (true) { try { partReleaseFut.get(2 * cctx.gridConfig().getNetworkTimeout(), TimeUnit.MILLISECONDS); break; } catch (IgniteFutureTimeoutCheckedException ignored) { // Print pending transactions and locks that might have led to hang. dumpPendingObjects(); } } if (log.isDebugEnabled()) log.debug("After waiting for partition release future: " + this); if (!F.isEmpty(reqs)) blockGateways(); if (exchId.isLeft()) cctx.mvcc().removeExplicitNodeLocks(exchId.nodeId(), exchId.topologyVersion()); IgniteInternalFuture<?> locksFut = cctx.mvcc().finishLocks(exchId.topologyVersion()); while (true) { try { locksFut.get(2 * cctx.gridConfig().getNetworkTimeout(), TimeUnit.MILLISECONDS); break; } catch (IgniteFutureTimeoutCheckedException ignored) { U.warn( log, "Failed to wait for locks release future. " + "Dumping pending objects that might be the cause: " + cctx.localNodeId()); U.warn(log, "Locked entries:"); Map<IgniteTxKey, Collection<GridCacheMvccCandidate>> locks = cctx.mvcc().unfinishedLocks(exchId.topologyVersion()); for (Map.Entry<IgniteTxKey, Collection<GridCacheMvccCandidate>> e : locks.entrySet()) U.warn(log, "Locked entry [key=" + e.getKey() + ", mvcc=" + e.getValue() + ']'); } } for (GridCacheContext cacheCtx : cctx.cacheContexts()) { if (cacheCtx.isLocal()) continue; // Notify replication manager. GridCacheContext drCacheCtx = cacheCtx.isNear() ? cacheCtx.near().dht().context() : cacheCtx; if (drCacheCtx.isDrEnabled()) drCacheCtx.dr().beforeExchange(topVer, exchId.isLeft()); // Partition release future is done so we can flush the write-behind store. cacheCtx.store().forceFlush(); // Process queued undeploys prior to sending/spreading map. cacheCtx.preloader().unwindUndeploys(); GridDhtPartitionTopology top = cacheCtx.topology(); assert topVer.equals(top.topologyVersion()) : "Topology version is updated only in this class instances inside single ExchangeWorker thread."; top.beforeExchange(this); } for (GridClientPartitionTopology top : cctx.exchange().clientTopologies()) { top.updateTopologyVersion(exchId, this, -1, stopping(top.cacheId())); top.beforeExchange(this); } } catch (IgniteInterruptedCheckedException e) { onDone(e); throw e; } catch (Throwable e) { U.error( log, "Failed to reinitialize local partitions (preloading will be stopped): " + exchId, e); onDone(e); if (e instanceof Error) throw (Error) e; return; } if (F.isEmpty(rmtIds)) { onDone(exchId.topologyVersion()); return; } ready.set(true); initFut.onDone(true); if (log.isDebugEnabled()) log.debug("Initialized future: " + this); // If this node is not oldest. if (!oldestNode.get().id().equals(cctx.localNodeId())) sendPartitions(); else { boolean allReceived = allReceived(); if (allReceived && replied.compareAndSet(false, true)) { if (spreadPartitions()) onDone(exchId.topologyVersion()); } } scheduleRecheck(); } else assert false : "Skipped init future: " + this; }
public static boolean testRendezvousChannel() { final int SERVER_THREADS = 10; final int CLIENT_THREADS = 10; final int SERVER_MAX_TIMEOUT = 20; final int CLIENT_MAX_TIMEOUT = 100; final int TIMEOUT_PERCENT = 50; final int MAX_SERVICE_TIME = 30; final int EXIT_TIME = 50; final int FAILURES_PERCENT = 1; Thread[] servers = new Thread[SERVER_THREADS]; Thread[] clients = new Thread[CLIENT_THREADS]; final RendezvousChannel_<Integer, Integer> rvc = new RendezvousChannel_<Integer, Integer>(); final AtomicBoolean shutdown = new AtomicBoolean(); final int[] successfulServices = new int[SERVER_THREADS]; final int[] failedServices = new int[SERVER_THREADS]; final int[] successfulRequests = new int[CLIENT_THREADS]; final int[] failedRequests = new int[CLIENT_THREADS]; // // Create and start the server threads. // for (int i = 0; i < SERVER_THREADS; i++) { final int tid = i; servers[i] = new Thread() { public void run() { Random r = new Random(tid); int count = 0; int timeouts = 0; long timeout; System.out.println("++server #" + tid + " started..."); // loops: // do { RendezvousChannel.RendezVousToken<Integer, Integer> request; try { timeout = r.nextInt(100) < TIMEOUT_PERCENT ? r.nextInt(SERVER_MAX_TIMEOUT) : -1L; timeout = 100; while ((request = rvc.accept(timeout)) == null) { timeouts++; // if (shutdown.get()) { // break loops; // } } // // Simulate the service time. // sleepCatchingInterrupt(r.nextInt(MAX_SERVICE_TIME)); // // Compute the result doubling the request argument. // int serviceResult = request.service.intValue() << 1; // // Inject failures. // if (r.nextInt(100) < FAILURES_PERCENT) { serviceResult++; // fail! failedServices[tid]++; } else { successfulServices[tid]++; } // // Reply with the service result. // rvc.reply(request, serviceResult); // // Increment service count and periodically display the "alive" message. // if ((++count % 100) == 0) { System.out.print("[s#" + tid + "]"); } } catch (InterruptedException ie) { } // } while (!shutdown.get()); // // Show server thread results. // System.out.println( "--server #" + tid + " exiting, " + count + " requests accepted, " + timeouts + " timed out"); } }; servers[i].start(); } // Create and start the client threads. for (int i = 0; i < CLIENT_THREADS; i++) { final int tid = i; clients[i] = new Thread() { public void run() { Random r = new Random(tid + SERVER_THREADS); int count = 0; int timeouts = 0; System.out.println("++client #" + tid + " started..."); // loops: // do { Integer response; try { long timeout = r.nextInt(100) < TIMEOUT_PERCENT ? r.nextInt(CLIENT_MAX_TIMEOUT) : -1L; timeout = 100; int serviceArgument = tid + 1; while ((response = rvc.request(serviceArgument, timeout)) == null) { timeouts++; // if (shutdown.get()) { // break loops; // } } int serviceResult = response.intValue(); if (serviceResult == serviceArgument << 1) { successfulRequests[tid]++; } else { failedRequests[tid]++; /* System.out.println("\n!!client #" + tid + " service failure: expected/received " + (serviceArgument << 1) + "/" + serviceResult); */ } // // Increment request count and periodically display the "alive" menssage. // if ((++count % 100) == 0) { System.out.print("[c#" + tid + "]"); } } catch (InterruptedException ie) { } // } while (!shutdown.get()); System.out.println( "--client #" + tid + " exiting, " + count + " requests processed, " + timeouts + " timed out"); } }; clients[i].start(); } // // Run the test until <enter> and then set the shutdown flag. // System.out.print("\n+++ hit <enter> to terminate the test..."); readln(); shutdown.set(true); // // Sleep for a while to let all threads exited. // sleepCatchingInterrupt(EXIT_TIME); // // Wait until all client threads have been exited. // for (int i = 0; i < CLIENT_THREADS; i++) { if (clients[i].isAlive()) { System.out.println("!!! client #" + i + " is still alive, so it will be interrupted"); clients[i].interrupt(); } joinUninterruptibly(clients[i]); } // // Wait until all server threads have been exited. // for (int i = 0; i < SERVER_THREADS; i++) { if (servers[i].isAlive()) { System.out.println("!!! server #" + i + " is still alive, so it will be interrupted"); servers[i].interrupt(); } joinUninterruptibly(servers[i]); } // // Compute and display results. // long sumFailedRequests = 0, sumSuccessfulRequests = 0; for (int i = 0; i < CLIENT_THREADS; i++) { sumSuccessfulRequests += successfulRequests[i]; sumFailedRequests += failedRequests[i]; } long sumFailedServices = 0, sumSuccessfulServices = 0; for (int i = 0; i < SERVER_THREADS; i++) { sumSuccessfulServices += successfulServices[i]; sumFailedServices += failedServices[i]; } System.out.println( "+++ successfull requests/services: " + sumSuccessfulRequests + "/" + sumSuccessfulServices + ", failed requests/services: " + sumFailedRequests + "/" + sumFailedServices); return sumSuccessfulRequests == sumSuccessfulServices && sumFailedRequests == sumFailedServices; }
/** * Asynchronous sequence update operation. Will add given amount to the sequence value. * * @param l Increment amount. * @param updateCall Cache call that will update sequence reservation count in accordance with l. * @param updated If {@code true}, will return sequence value after update, otherwise will return * sequence value prior to update. * @return Future indicating sequence value. * @throws GridException If update failed. */ private GridFuture<Long> internalUpdateAsync( long l, @Nullable Callable<Long> updateCall, boolean updated) throws GridException { checkRemoved(); A.ensure(l > 0, " Parameter mustn't be less then 1: " + l); lock.lock(); try { // If reserved range isn't exhausted. if (locVal + l <= upBound) { long curVal = locVal; locVal += l; return new GridFinishedFuture<Long>(ctx.kernalContext(), updated ? locVal : curVal); } } finally { lock.unlock(); } if (updateCall == null) updateCall = internalUpdate(l, updated); while (true) { if (updateGuard.compareAndSet(false, true)) { try { // This call must be outside lock. return ctx.closures().callLocalSafe(updateCall, true); } finally { lock.lock(); try { updateGuard.set(false); cond.signalAll(); } finally { lock.unlock(); } } } else { lock.lock(); try { while (locVal >= upBound && updateGuard.get()) { try { cond.await(500, MILLISECONDS); } catch (InterruptedException e) { throw new GridInterruptedException(e); } } checkRemoved(); // If reserved range isn't exhausted. if (locVal + l <= upBound) { long curVal = locVal; locVal += l; return new GridFinishedFuture<Long>(ctx.kernalContext(), updated ? locVal : curVal); } } finally { lock.unlock(); } } } }
/** * Synchronous sequence update operation. Will add given amount to the sequence value. * * @param l Increment amount. * @param updateCall Cache call that will update sequence reservation count in accordance with l. * @param updated If {@code true}, will return sequence value after update, otherwise will return * sequence value prior to update. * @return Sequence value. * @throws GridException If update failed. */ private long internalUpdate(long l, @Nullable Callable<Long> updateCall, boolean updated) throws GridException { checkRemoved(); assert l > 0; lock.lock(); try { // If reserved range isn't exhausted. if (locVal + l <= upBound) { long curVal = locVal; locVal += l; return updated ? locVal : curVal; } } finally { lock.unlock(); } if (updateCall == null) updateCall = internalUpdate(l, updated); while (true) { if (updateGuard.compareAndSet(false, true)) { try { // This call must be outside lock. return CU.outTx(updateCall, ctx); } finally { lock.lock(); try { updateGuard.set(false); cond.signalAll(); } finally { lock.unlock(); } } } else { lock.lock(); try { while (locVal >= upBound && updateGuard.get()) { try { cond.await(500, MILLISECONDS); } catch (InterruptedException e) { throw new GridInterruptedException(e); } } checkRemoved(); // If reserved range isn't exhausted. if (locVal + l <= upBound) { long curVal = locVal; locVal += l; return updated ? locVal : curVal; } } finally { lock.unlock(); } } } }
/** * JUnit. * * @throws Exception If failed. */ @SuppressWarnings({"TooBroadScope"}) public void testRestarts() throws Exception { int duration = 60 * 1000; int qryThreadNum = 10; final long nodeLifeTime = 2 * 1000; final int logFreq = 20; final IgniteCache<Integer, Integer> cache = grid(0).cache(null); assert cache != null; for (int i = 0; i < KEY_CNT; i++) cache.put(i, i); assertEquals(KEY_CNT, cache.localSize()); final AtomicInteger qryCnt = new AtomicInteger(); final AtomicBoolean done = new AtomicBoolean(); IgniteInternalFuture<?> fut1 = multithreadedAsync( new CAX() { @Override public void applyx() throws IgniteCheckedException { while (!done.get()) { Collection<Cache.Entry<Integer, Integer>> res = cache.query(new SqlQuery(Integer.class, "_val >= 0")).getAll(); assertFalse(res.isEmpty()); int c = qryCnt.incrementAndGet(); if (c % logFreq == 0) info("Executed queries: " + c); } } }, qryThreadNum); final AtomicInteger restartCnt = new AtomicInteger(); CollectingEventListener lsnr = new CollectingEventListener(); for (int i = 0; i < GRID_CNT; i++) grid(i).events().localListen(lsnr, EventType.EVT_CACHE_REBALANCE_STOPPED); IgniteInternalFuture<?> fut2 = multithreadedAsync( new Callable<Object>() { @SuppressWarnings({"BusyWait"}) @Override public Object call() throws Exception { while (!done.get()) { int idx = GRID_CNT; startGrid(idx); Thread.sleep(nodeLifeTime); stopGrid(idx); int c = restartCnt.incrementAndGet(); if (c % logFreq == 0) info("Node restarts: " + c); } return true; } }, 1); Thread.sleep(duration); done.set(true); fut1.get(); fut2.get(); info("Awaiting rebalance events [restartCnt=" + restartCnt.get() + ']'); boolean success = lsnr.awaitEvents(GRID_CNT * 2 * restartCnt.get(), 15000); for (int i = 0; i < GRID_CNT; i++) grid(i).events().stopLocalListen(lsnr, EventType.EVT_CACHE_REBALANCE_STOPPED); assert success; }
public void signalLoopbreak() { loopBreaker.set(true); if (mySelector != null) mySelector.wakeup(); }
/** * JUnit. * * @throws Exception In case of error. */ @SuppressWarnings({"TooBroadScope"}) public void testH2Text() throws Exception { int duration = 60 * 1000; final int keyCnt = 5000; final int logFreq = 50; final String txt = "Value"; final GridCache<Integer, H2TextValue> c = grid(0).cache(null); GridFuture<?> fut1 = multithreadedAsync( new Callable() { @Override public Object call() throws Exception { for (int i = 0; i < keyCnt; i++) { c.putx(i, new H2TextValue(txt)); if (i % logFreq == 0) X.println("Stored values: " + i); } return null; } }, 1); // Create query. final GridCacheQuery<Map.Entry<Integer, H2TextValue>> qry = c.queries().createFullTextQuery(H2TextValue.class, txt); qry.enableDedup(false); qry.includeBackups(false); qry.timeout(TEST_TIMEOUT); final AtomicBoolean stop = new AtomicBoolean(); GridFuture<?> fut2 = multithreadedAsync( new Callable() { @Override public Object call() throws Exception { int cnt = 0; while (!stop.get()) { Collection<Map.Entry<Integer, H2TextValue>> res = qry.execute().get(); cnt++; if (cnt % logFreq == 0) { X.println("Result set: " + res.size()); X.println("Executed queries: " + cnt); } } return null; } }, 1); Thread.sleep(duration); fut1.get(); stop.set(true); fut2.get(); }
@Override public void cancelWaitForPairing() { logger.info("Pairing stopped"); waitingForPairing.set(false); pairingListener = null; }
/** {@inheritDoc} */ @Override public void setExcludePaths(@Nullable Collection<String> excludePaths) { this.excludePaths = excludePaths; excludeRecompile.set(true); }
/** * @param cacheMode Cache mode. * @param sameAff If {@code false} uses different number of partitions for caches. * @param concurrency Transaction concurrency. * @param isolation Transaction isolation. * @throws Exception If failed. */ private void crossCacheTxFailover( CacheMode cacheMode, boolean sameAff, final TransactionConcurrency concurrency, final TransactionIsolation isolation) throws Exception { IgniteKernal ignite0 = (IgniteKernal) ignite(0); final AtomicBoolean stop = new AtomicBoolean(); try { ignite0.createCache(cacheConfiguration(CACHE1, cacheMode, 256)); ignite0.createCache(cacheConfiguration(CACHE2, cacheMode, sameAff ? 256 : 128)); final AtomicInteger threadIdx = new AtomicInteger(); IgniteInternalFuture<?> fut = GridTestUtils.runMultiThreadedAsync( new Callable<Void>() { @Override public Void call() throws Exception { int idx = threadIdx.getAndIncrement(); Ignite ignite = ignite(idx % GRID_CNT); log.info( "Started update thread [node=" + ignite.name() + ", client=" + ignite.configuration().isClientMode() + ']'); IgniteCache<TestKey, TestValue> cache1 = ignite.cache(CACHE1); IgniteCache<TestKey, TestValue> cache2 = ignite.cache(CACHE2); assertNotSame(cache1, cache2); IgniteTransactions txs = ignite.transactions(); ThreadLocalRandom rnd = ThreadLocalRandom.current(); long iter = 0; while (!stop.get()) { boolean sameKey = rnd.nextBoolean(); try { try (Transaction tx = txs.txStart(concurrency, isolation)) { if (sameKey) { TestKey key = new TestKey(rnd.nextLong(KEY_RANGE)); cacheOperation(rnd, cache1, key); cacheOperation(rnd, cache2, key); } else { TestKey key1 = new TestKey(rnd.nextLong(KEY_RANGE)); TestKey key2 = new TestKey(key1.key() + 1); cacheOperation(rnd, cache1, key1); cacheOperation(rnd, cache2, key2); } tx.commit(); } } catch (CacheException | IgniteException e) { log.info("Update error: " + e); } if (iter++ % 500 == 0) log.info("Iteration: " + iter); } return null; } /** * @param rnd Random. * @param cache Cache. * @param key Key. */ private void cacheOperation( ThreadLocalRandom rnd, IgniteCache<TestKey, TestValue> cache, TestKey key) { switch (rnd.nextInt(4)) { case 0: cache.put(key, new TestValue(rnd.nextLong())); break; case 1: cache.remove(key); break; case 2: cache.invoke(key, new TestEntryProcessor(rnd.nextBoolean() ? 1L : null)); break; case 3: cache.get(key); break; default: assert false; } } }, 10, "tx-thread"); long stopTime = System.currentTimeMillis() + 3 * 60_000; long topVer = ignite0.cluster().topologyVersion(); boolean failed = false; while (System.currentTimeMillis() < stopTime) { log.info("Start node."); IgniteKernal ignite = (IgniteKernal) startGrid(GRID_CNT); assertFalse(ignite.configuration().isClientMode()); topVer++; IgniteInternalFuture<?> affFut = ignite .context() .cache() .context() .exchange() .affinityReadyFuture(new AffinityTopologyVersion(topVer)); try { if (affFut != null) affFut.get(30_000); } catch (IgniteFutureTimeoutCheckedException e) { log.error("Failed to wait for affinity future after start: " + topVer); failed = true; break; } Thread.sleep(500); log.info("Stop node."); stopGrid(GRID_CNT); topVer++; affFut = ignite0 .context() .cache() .context() .exchange() .affinityReadyFuture(new AffinityTopologyVersion(topVer)); try { if (affFut != null) affFut.get(30_000); } catch (IgniteFutureTimeoutCheckedException e) { log.error("Failed to wait for affinity future after stop: " + topVer); failed = true; break; } } stop.set(true); fut.get(); assertFalse("Test failed, see log for details.", failed); } finally { stop.set(true); ignite0.destroyCache(CACHE1); ignite0.destroyCache(CACHE2); awaitPartitionMapExchange(); } }