/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ignite.internal.processors.cluster; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteCompute; import org.apache.ignite.IgniteException; import org.apache.ignite.IgniteLogger; import org.apache.ignite.cluster.ClusterNode; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.events.DiscoveryEvent; import org.apache.ignite.events.Event; import org.apache.ignite.internal.GridKernalContext; import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.IgniteInterruptedCheckedException; import org.apache.ignite.internal.cluster.ClusterGroupAdapter; import org.apache.ignite.internal.managers.discovery.CustomEventListener; import org.apache.ignite.internal.managers.eventstorage.GridLocalEventListener; import org.apache.ignite.internal.pagemem.store.IgnitePageStoreManager; import org.apache.ignite.internal.processors.GridProcessorAdapter; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; import org.apache.ignite.internal.processors.cache.ChangeGlobalStateMessage; import org.apache.ignite.internal.processors.cache.ClusterState; import org.apache.ignite.internal.processors.cache.DynamicCacheChangeBatch; import org.apache.ignite.internal.processors.cache.DynamicCacheChangeRequest; import org.apache.ignite.internal.processors.cache.GridCacheProcessor; import org.apache.ignite.internal.processors.cache.GridCacheSharedContext; import org.apache.ignite.internal.processors.cache.GridChangeGlobalStateMessageResponse; import org.apache.ignite.internal.util.future.GridFinishedFuture; import org.apache.ignite.internal.util.future.GridFutureAdapter; import org.apache.ignite.internal.util.tostring.GridToStringExclude; import org.apache.ignite.internal.util.tostring.GridToStringInclude; import org.apache.ignite.internal.util.typedef.CI1; import org.apache.ignite.internal.util.typedef.CI2; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.CU; import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.lang.IgniteFuture; import org.apache.ignite.lang.IgniteRunnable; import org.apache.ignite.resources.IgniteInstanceResource; import org.apache.ignite.spi.discovery.DiscoveryDataBag; import org.jetbrains.annotations.Nullable; import static org.apache.ignite.events.EventType.EVT_NODE_FAILED; import static org.apache.ignite.events.EventType.EVT_NODE_LEFT; import static org.apache.ignite.internal.managers.communication.GridIoPolicy.SYSTEM_POOL; import static org.apache.ignite.internal.processors.cache.ClusterState.ACTIVE; import static org.apache.ignite.internal.processors.cache.ClusterState.INACTIVE; import static org.apache.ignite.internal.processors.cache.ClusterState.TRANSITION; /** * */ public class GridClusterStateProcessor extends GridProcessorAdapter { /** Global status. */ private volatile ClusterState globalState; /** Action context. */ private volatile ChangeGlobalStateContext lastCgsCtx; /** Local action future. */ private final AtomicReference<GridChangeGlobalStateFuture> cgsLocFut = new AtomicReference<>(); /** Process. */ @GridToStringExclude private GridCacheProcessor cacheProc; /** Shared context. */ @GridToStringExclude private GridCacheSharedContext<?, ?> sharedCtx; //todo may be add init latch /** Listener. */ private final GridLocalEventListener lsr = new GridLocalEventListener() { @Override public void onEvent(Event evt) { assert evt != null; final DiscoveryEvent e = (DiscoveryEvent)evt; assert e.type() == EVT_NODE_LEFT || e.type() == EVT_NODE_FAILED : this; final GridChangeGlobalStateFuture f = cgsLocFut.get(); if (f != null) f.initFut.listen(new CI1<IgniteInternalFuture>() { @Override public void apply(IgniteInternalFuture fut) { f.onDiscoveryEvent(e); } }); } }; /** * @param ctx Kernal context. */ public GridClusterStateProcessor(GridKernalContext ctx) { super(ctx); } /** {@inheritDoc} */ @Override public void start(boolean activeOnStart) throws IgniteCheckedException { super.start(activeOnStart); globalState = activeOnStart ? ACTIVE : INACTIVE; cacheProc = ctx.cache(); sharedCtx = cacheProc.context(); sharedCtx.io().addHandler(0, GridChangeGlobalStateMessageResponse.class, new CI2<UUID, GridChangeGlobalStateMessageResponse>() { @Override public void apply(UUID nodeId, GridChangeGlobalStateMessageResponse msg) { processChangeGlobalStateResponse(nodeId, msg); } }); ctx.discovery().setCustomEventListener( ChangeGlobalStateMessage.class, new CustomEventListener<ChangeGlobalStateMessage>() { @Override public void onCustomEvent( AffinityTopologyVersion topVer, ClusterNode snd, ChangeGlobalStateMessage msg) { assert topVer != null; assert snd != null; assert msg != null; boolean activate = msg.activate(); ChangeGlobalStateContext actx = lastCgsCtx; if (actx != null && globalState == TRANSITION) { GridChangeGlobalStateFuture f = cgsLocFut.get(); if (log.isDebugEnabled()) log.debug("Concurrent " + prettyStr(activate) + " [id=" + ctx.localNodeId() + " topVer=" + topVer + " actx=" + actx + ", msg=" + msg + "]"); if (f != null && f.requestId.equals(msg.requestId())) f.onDone(new IgniteCheckedException( "Concurrent change state, now in progress=" + (activate) + ", initiatingNodeId=" + actx.initiatingNodeId + ", you try=" + (prettyStr(activate)) + ", locNodeId=" + ctx.localNodeId() )); msg.concurrentChangeState(); } else { if (log.isInfoEnabled()) log.info("Create " + prettyStr(activate) + " context [id=" + ctx.localNodeId() + " topVer=" + topVer + ", reqId=" + msg.requestId() + ", initiatingNodeId=" + msg.initiatorNodeId() + "]"); lastCgsCtx = new ChangeGlobalStateContext( msg.requestId(), msg.initiatorNodeId(), msg.getDynamicCacheChangeBatch(), msg.activate()); globalState = TRANSITION; } } }); ctx.event().addLocalEventListener(lsr, EVT_NODE_LEFT, EVT_NODE_FAILED); } /** {@inheritDoc} */ @Override public void stop(boolean cancel) throws IgniteCheckedException { super.stop(cancel); sharedCtx.io().removeHandler(0, GridChangeGlobalStateMessageResponse.class); ctx.event().removeLocalEventListener(lsr, EVT_NODE_LEFT, EVT_NODE_FAILED); IgniteCheckedException stopErr = new IgniteInterruptedCheckedException( "Node is stopping: " + ctx.igniteInstanceName()); GridChangeGlobalStateFuture f = cgsLocFut.get(); if (f != null) f.onDone(stopErr); cgsLocFut.set(null); } /** {@inheritDoc} */ @Nullable @Override public DiscoveryDataExchangeType discoveryDataType() { return DiscoveryDataExchangeType.STATE_PROC; } /** {@inheritDoc} */ @Override public void collectGridNodeData(DiscoveryDataBag dataBag) { dataBag.addGridCommonData(DiscoveryDataExchangeType.STATE_PROC.ordinal(), globalState); } /** {@inheritDoc} */ @Override public void onGridDataReceived(DiscoveryDataBag.GridDiscoveryData data) { ClusterState state = (ClusterState)data.commonData(); if (state != null) globalState = state; } /** * */ public IgniteInternalFuture<?> changeGlobalState(final boolean activate) { if (cacheProc.transactions().tx() != null || sharedCtx.lockedTopologyVersion(null) != null) throw new IgniteException("Cannot " + prettyStr(activate) + " cluster, because cache locked on transaction."); if ((globalState == ACTIVE && activate) || (this.globalState == INACTIVE && !activate)) return new GridFinishedFuture<>(); final UUID requestId = UUID.randomUUID(); final GridChangeGlobalStateFuture cgsFut = new GridChangeGlobalStateFuture(requestId, activate, ctx); if (!cgsLocFut.compareAndSet(null, cgsFut)) { GridChangeGlobalStateFuture locF = cgsLocFut.get(); if (locF.activate == activate) return locF; else return new GridFinishedFuture<>(new IgniteException( "fail " + prettyStr(activate) + ", because now in progress" + prettyStr(locF.activate))); } try { if (ctx.clientNode()) { AffinityTopologyVersion topVer = ctx.discovery().topologyVersionEx(); IgniteCompute comp = ((ClusterGroupAdapter)ctx.cluster().get().forServers()) .compute().withAsync(); if (log.isInfoEnabled()) log.info("Send " + prettyStr(activate) + " request from client node [id=" + ctx.localNodeId() + " topVer=" + topVer + " ]"); comp.run(new ClientChangeGlobalStateComputeRequest(activate)); comp.future().listen(new CI1<IgniteFuture>() { @Override public void apply(IgniteFuture fut) { try { fut.get(); cgsFut.onDone(); } catch (Exception e) { cgsFut.onDone(e); } } }); } else { List<DynamicCacheChangeRequest> reqs = new ArrayList<>(); DynamicCacheChangeRequest changeGlobalStateReq = new DynamicCacheChangeRequest( requestId, null, ctx.localNodeId()); changeGlobalStateReq.state(activate ? ACTIVE : INACTIVE); reqs.add(changeGlobalStateReq); reqs.addAll(activate ? cacheProc.startAllCachesRequests() : cacheProc.stopAllCachesRequests()); ChangeGlobalStateMessage changeGlobalStateMsg = new ChangeGlobalStateMessage( requestId, ctx.localNodeId(), activate, new DynamicCacheChangeBatch(reqs)); try { ctx.discovery().sendCustomEvent(changeGlobalStateMsg); if (ctx.isStopping()) cgsFut.onDone(new IgniteCheckedException("Failed to execute " + prettyStr(activate) + " request, " + "node is stopping.")); } catch (IgniteCheckedException e) { log.error("Fail create or send change global state request." + cgsFut, e); cgsFut.onDone(e); } } } catch (IgniteCheckedException e) { log.error("Fail create or send change global state request." + cgsFut, e); cgsFut.onDone(e); } return cgsFut; } /** * */ public boolean active() { ChangeGlobalStateContext actx = lastCgsCtx; if (actx != null && !actx.activate && globalState == TRANSITION) return true; if (actx != null && actx.activate && globalState == TRANSITION) return false; return globalState == ACTIVE; } /** * @param reqs Requests. */ public boolean changeGlobalState( Collection<DynamicCacheChangeRequest> reqs, AffinityTopologyVersion topVer ) { assert !F.isEmpty(reqs); assert topVer != null; for (DynamicCacheChangeRequest req : reqs) if (req.globalStateChange()) { ChangeGlobalStateContext cgsCtx = lastCgsCtx; assert cgsCtx != null : "reqs: " + Arrays.toString(reqs.toArray()); cgsCtx.topologyVersion(topVer); return true; } return false; } /** * Invoke from exchange future. */ public Exception onChangeGlobalState() { GridChangeGlobalStateFuture f = cgsLocFut.get(); ChangeGlobalStateContext cgsCtx = lastCgsCtx; assert cgsCtx != null; if (f != null) f.setRemaining(cgsCtx.topVer); return cgsCtx.activate ? onActivate(cgsCtx) : onDeActivate(cgsCtx); } /** * @param exs Exs. */ public void onFullResponseMessage(Map<UUID, Exception> exs) { assert !F.isEmpty(exs); ChangeGlobalStateContext actx = lastCgsCtx; actx.setFail(); // revert change if activation request fail if (actx.activate) { try { cacheProc.onKernalStopCaches(true); cacheProc.stopCaches(true); sharedCtx.affinity().removeAllCacheInfo(); if (!ctx.clientNode()) { sharedCtx.database().onDeActivate(ctx); if (sharedCtx.pageStore() != null) sharedCtx.pageStore().onDeActivate(ctx); if (sharedCtx.wal() != null) sharedCtx.wal().onDeActivate(ctx); } } catch (Exception e) { for (Map.Entry<UUID, Exception> entry : exs.entrySet()) e.addSuppressed(entry.getValue()); log.error("Fail while revert activation request changes", e); } } else { //todo revert change if deactivate request fail } globalState = actx.activate ? INACTIVE : ACTIVE; GridChangeGlobalStateFuture af = cgsLocFut.get(); if (af != null && af.requestId.equals(actx.requestId)) { IgniteCheckedException e = new IgniteCheckedException("see suppressed"); for (Map.Entry<UUID, Exception> entry : exs.entrySet()) e.addSuppressed(entry.getValue()); af.onDone(e); } } /** * */ private Exception onActivate(ChangeGlobalStateContext cgsCtx) { final boolean client = ctx.clientNode(); if (log.isInfoEnabled()) log.info("Start activation process [nodeId=" + this.ctx.localNodeId() + ", client=" + client + ", topVer=" + cgsCtx.topVer + "]"); Collection<CacheConfiguration> cfgs = new ArrayList<>(); for (DynamicCacheChangeRequest req : cgsCtx.batch.requests()) { if (req.startCacheConfiguration() != null) cfgs.add(req.startCacheConfiguration()); } try { if (!client) { sharedCtx.database().lock(); IgnitePageStoreManager pageStore = sharedCtx.pageStore(); if (pageStore != null) pageStore.onActivate(ctx); if (sharedCtx.wal() != null) sharedCtx.wal().onActivate(ctx); sharedCtx.database().initDataBase(); for (CacheConfiguration cfg : cfgs) { if (CU.isSystemCache(cfg.getName())) if (pageStore != null) pageStore.initializeForCache(cfg); } for (CacheConfiguration cfg : cfgs) { if (!CU.isSystemCache(cfg.getName())) if (pageStore != null) pageStore.initializeForCache(cfg); } sharedCtx.database().onActivate(ctx); } if (log.isInfoEnabled()) log.info("Success activate wal, dataBase, pageStore [nodeId=" + ctx.localNodeId() + ", client=" + client + ", topVer=" + cgsCtx.topVer + "]"); return null; } catch (Exception e) { log.error("Fail activate wal, dataBase, pageStore [nodeId=" + ctx.localNodeId() + ", client=" + client + ", topVer=" + cgsCtx.topVer + "]", e); if (!ctx.clientNode()) sharedCtx.database().unLock(); return e; } } /** * */ public Exception onDeActivate(ChangeGlobalStateContext cgsCtx) { final boolean client = ctx.clientNode(); if (log.isInfoEnabled()) log.info("Start deactivate process [id=" + ctx.localNodeId() + ", client=" + client + ", topVer=" + cgsCtx.topVer + "]"); try { ctx.dataStructures().onDeActivate(ctx); ctx.service().onDeActivate(ctx); if (log.isInfoEnabled()) log.info("Success deactivate services, dataStructures, database, pageStore, wal [id=" + ctx.localNodeId() + ", client=" + client + ", topVer=" + cgsCtx.topVer + "]"); return null; } catch (Exception e) { log.error("DeActivation fail [nodeId=" + ctx.localNodeId() + ", client=" + client + ", topVer=" + cgsCtx.topVer + "]", e); return e; } finally { if (!client) sharedCtx.database().unLock(); } } /** * */ private void onFinalActivate(final ChangeGlobalStateContext cgsCtx) { IgniteInternalFuture<?> asyncActivateFut = ctx.closure().runLocalSafe(new Runnable() { @Override public void run() { boolean client = ctx.clientNode(); Exception e = null; try { if (!ctx.config().isDaemon()) ctx.cacheObjects().onUtilityCacheStarted(); ctx.service().onUtilityCacheStarted(); ctx.service().onActivate(ctx); ctx.dataStructures().onActivate(ctx); if (log.isInfoEnabled()) log.info("Success final activate [nodeId=" + ctx.localNodeId() + ", client=" + client + ", topVer=" + cgsCtx.topVer + "]"); } catch (Exception ex) { e = ex; log.error("Fail activate finished [nodeId=" + ctx.localNodeId() + ", client=" + client + ", topVer=" + GridClusterStateProcessor.this.lastCgsCtx.topVer + "]", ex); } finally { globalState = ACTIVE; sendChangeGlobalStateResponse(cgsCtx.requestId, cgsCtx.initiatingNodeId, e); GridClusterStateProcessor.this.lastCgsCtx = null; } } }); cgsCtx.setAsyncActivateFut(asyncActivateFut); } /** * */ public void onFinalDeActivate(ChangeGlobalStateContext cgsCtx) { final boolean client = ctx.clientNode(); if (log.isInfoEnabled()) log.info("Success final deactivate [nodeId=" + ctx.localNodeId() + ", client=" + client + ", topVer=" + cgsCtx.topVer + "]"); Exception ex = null; try { if (!client) { sharedCtx.database().onDeActivate(ctx); if (sharedCtx.pageStore() != null) sharedCtx.pageStore().onDeActivate(ctx); if (sharedCtx.wal() != null) sharedCtx.wal().onDeActivate(ctx); sharedCtx.affinity().removeAllCacheInfo(); } } catch (Exception e) { ex = e; } finally { globalState = INACTIVE; } sendChangeGlobalStateResponse(cgsCtx.requestId, cgsCtx.initiatingNodeId, ex); this.lastCgsCtx = null; } /** * */ public void onExchangeDone() { ChangeGlobalStateContext cgsCtx = lastCgsCtx; assert cgsCtx != null; if (!cgsCtx.isFail()) { if (cgsCtx.activate) onFinalActivate(cgsCtx); else onFinalDeActivate(cgsCtx); } else lastCgsCtx = null; } /** * @param initNodeId Initialize node id. * @param ex Exception. */ private void sendChangeGlobalStateResponse(UUID requestId, UUID initNodeId, Exception ex) { assert requestId != null; assert initNodeId != null; try { GridChangeGlobalStateMessageResponse actResp = new GridChangeGlobalStateMessageResponse(requestId, ex); if (log.isDebugEnabled()) log.debug("Send change global state response [nodeId=" + ctx.localNodeId() + ", topVer=" + ctx.discovery().topologyVersionEx() + ", response=" + actResp + "]"); if (ctx.localNodeId().equals(initNodeId)) processChangeGlobalStateResponse(ctx.localNodeId(), actResp); else sharedCtx.io().send(initNodeId, actResp, SYSTEM_POOL); } catch (IgniteCheckedException e) { log.error("Fail send change global state response to " + initNodeId, e); } } /** * @param msg Message. */ private void processChangeGlobalStateResponse(final UUID nodeId, final GridChangeGlobalStateMessageResponse msg) { assert nodeId != null; assert msg != null; if (log.isDebugEnabled()) log.debug("Received activation response [requestId=" + msg.getRequestId() + ", nodeId=" + nodeId + "]"); ClusterNode node = ctx.discovery().node(nodeId); if (node == null) { U.warn(log, "Received activation response from unknown node (will ignore) [requestId=" + msg.getRequestId() + ']'); return; } UUID requestId = msg.getRequestId(); final GridChangeGlobalStateFuture fut = cgsLocFut.get(); if (fut != null && !fut.isDone() && requestId.equals(fut.requestId)) { fut.initFut.listen(new CI1<IgniteInternalFuture<?>>() { @Override public void apply(IgniteInternalFuture<?> f) { fut.onResponse(nodeId, msg); } }); } } /** * @param activate Activate. */ private String prettyStr(boolean activate) { return activate ? "activate" : "deactivate"; } /** {@inheritDoc} */ @Override public String toString() { return S.toString(GridClusterStateProcessor.class, this); } /** * */ private static class GridChangeGlobalStateFuture extends GridFutureAdapter { /** Request id. */ @GridToStringInclude private final UUID requestId; /** Activate. */ private final boolean activate; /** Nodes. */ @GridToStringInclude private final Set<UUID> remaining = new HashSet<>(); /** Responses. */ @GridToStringInclude private final Map<UUID, GridChangeGlobalStateMessageResponse> resps = new HashMap<>(); /** Context. */ @GridToStringExclude private final GridKernalContext ctx; /** */ @GridToStringExclude private final Object mux = new Object(); /** */ @GridToStringInclude private final GridFutureAdapter initFut = new GridFutureAdapter(); /** Grid logger. */ @GridToStringExclude private final IgniteLogger log; /** * */ public GridChangeGlobalStateFuture(UUID requestId, boolean activate, GridKernalContext ctx) { this.requestId = requestId; this.activate = activate; this.ctx = ctx; this.log = ctx.log(getClass()); } /** * @param event Event. */ public void onDiscoveryEvent(DiscoveryEvent event) { assert event != null; if (isDone()) return; boolean allReceived = false; synchronized (mux) { if (remaining.remove(event.eventNode().id())) allReceived = remaining.isEmpty(); } if (allReceived) onAllReceived(); } /** * */ public void setRemaining(AffinityTopologyVersion topVer) { Collection<ClusterNode> nodes = ctx.discovery().nodes(topVer); List<UUID> ids = new ArrayList<>(nodes.size()); for (ClusterNode n : nodes) ids.add(n.id()); if (log.isDebugEnabled()) log.debug("Setup remaining node [id=" + ctx.localNodeId() + ", client=" + ctx.clientNode() + ", topVer=" + ctx.discovery().topologyVersionEx() + ", nodes=" + Arrays.toString(ids.toArray()) + "]"); synchronized (mux) { remaining.addAll(ids); } initFut.onDone(); } /** * @param msg Activation message response. */ public void onResponse(UUID nodeId, GridChangeGlobalStateMessageResponse msg) { assert msg != null; if (isDone()) return; boolean allReceived = false; synchronized (mux) { if (remaining.remove(nodeId)) allReceived = remaining.isEmpty(); resps.put(nodeId, msg); } if (allReceived) onAllReceived(); } /** * */ private void onAllReceived() { Throwable e = new Throwable(); boolean fail = false; for (Map.Entry<UUID, GridChangeGlobalStateMessageResponse> entry : resps.entrySet()) { GridChangeGlobalStateMessageResponse r = entry.getValue(); if (r.getError() != null) { fail = true; e.addSuppressed(r.getError()); } } if (fail) onDone(e); else onDone(); } /** {@inheritDoc} */ @Override public boolean onDone(@Nullable Object res, @Nullable Throwable err) { ctx.state().cgsLocFut.set(null); return super.onDone(res, err); } /** {@inheritDoc} */ @Override public String toString() { return S.toString(GridChangeGlobalStateFuture.class, this); } } /** * * */ private static class ChangeGlobalStateContext { /** Request id. */ private final UUID requestId; /** Initiating node id. */ private final UUID initiatingNodeId; /** Batch requests. */ private final DynamicCacheChangeBatch batch; /** Activate. */ private final boolean activate; /** Topology version. */ private AffinityTopologyVersion topVer; /** Fail. */ private boolean fail; /** Async activate future. */ private IgniteInternalFuture<?> asyncActivateFut; /** * */ public ChangeGlobalStateContext( UUID requestId, UUID initiatingNodeId, DynamicCacheChangeBatch batch, boolean activate ) { this.requestId = requestId; this.batch = batch; this.activate = activate; this.initiatingNodeId = initiatingNodeId; } /** * @param topVer Topology version. */ public void topologyVersion(AffinityTopologyVersion topVer) { this.topVer = topVer; } /** * */ private void setFail() { fail = true; } /** * */ private boolean isFail() { return fail; } /** * */ public IgniteInternalFuture<?> getAsyncActivateFut() { return asyncActivateFut; } /** * @param asyncActivateFut Async activate future. */ public void setAsyncActivateFut(IgniteInternalFuture<?> asyncActivateFut) { this.asyncActivateFut = asyncActivateFut; } /** {@inheritDoc} */ @Override public String toString() { return S.toString(ChangeGlobalStateContext.class, this); } } /** * */ private static class ClientChangeGlobalStateComputeRequest implements IgniteRunnable { /** */ private static final long serialVersionUID = 0L; /** Activation. */ private final boolean activation; /** Ignite. */ @IgniteInstanceResource private Ignite ignite; /** * */ private ClientChangeGlobalStateComputeRequest(boolean activation) { this.activation = activation; } /** {@inheritDoc} */ @Override public void run() { ignite.active(activation); } } }