Search in sources :

Example 61 with GridCacheContext

use of org.apache.ignite.internal.processors.cache.GridCacheContext in project ignite by apache.

the class GridDhtPartitionDemander method handleSupplyMessage.

/**
 * Handles supply message from {@code nodeId} with specified {@code topicId}.
 *
 * Supply message contains entries to populate rebalancing partitions.
 *
 * There is a cyclic process:
 * Populate rebalancing partitions with entries from Supply message.
 * If not all partitions specified in {@link #rebalanceFut} were rebalanced or marked as missed
 * send new Demand message to request next batch of entries.
 *
 * @param topicId Topic id.
 * @param nodeId Node id.
 * @param supply Supply message.
 */
public void handleSupplyMessage(int topicId, final UUID nodeId, final GridDhtPartitionSupplyMessage supply) {
    AffinityTopologyVersion topVer = supply.topologyVersion();
    final RebalanceFuture fut = rebalanceFut;
    ClusterNode node = ctx.node(nodeId);
    if (node == null)
        return;
    if (// Topology already changed (for the future that supply message based on).
    topologyChanged(fut))
        return;
    if (!fut.isActual(supply.rebalanceId())) {
        // Supple message based on another future.
        return;
    }
    if (log.isDebugEnabled())
        log.debug("Received supply message [grp=" + grp.cacheOrGroupName() + ", msg=" + supply + ']');
    // Check whether there were class loading errors on unmarshal
    if (supply.classError() != null) {
        U.warn(log, "Rebalancing from node cancelled [grp=" + grp.cacheOrGroupName() + ", node=" + nodeId + "]. Class got undeployed during preloading: " + supply.classError());
        fut.cancel(nodeId);
        return;
    }
    final GridDhtPartitionTopology top = grp.topology();
    if (grp.sharedGroup()) {
        for (GridCacheContext cctx : grp.caches()) {
            if (cctx.statisticsEnabled()) {
                long keysCnt = supply.keysForCache(cctx.cacheId());
                if (keysCnt != -1)
                    cctx.cache().metrics0().onRebalancingKeysCountEstimateReceived(keysCnt);
                // Can not be calculated per cache.
                cctx.cache().metrics0().onRebalanceBatchReceived(supply.messageSize());
            }
        }
    } else {
        GridCacheContext cctx = grp.singleCacheContext();
        if (cctx.statisticsEnabled()) {
            if (supply.estimatedKeysCount() != -1)
                cctx.cache().metrics0().onRebalancingKeysCountEstimateReceived(supply.estimatedKeysCount());
            cctx.cache().metrics0().onRebalanceBatchReceived(supply.messageSize());
        }
    }
    try {
        AffinityAssignment aff = grp.affinity().cachedAffinity(topVer);
        GridCacheContext cctx = grp.sharedGroup() ? null : grp.singleCacheContext();
        // Preload.
        for (Map.Entry<Integer, CacheEntryInfoCollection> e : supply.infos().entrySet()) {
            int p = e.getKey();
            if (aff.get(p).contains(ctx.localNode())) {
                GridDhtLocalPartition part = top.localPartition(p, topVer, true);
                assert part != null;
                boolean last = supply.last().containsKey(p);
                if (part.state() == MOVING) {
                    boolean reserved = part.reserve();
                    assert reserved : "Failed to reserve partition [igniteInstanceName=" + ctx.igniteInstanceName() + ", grp=" + grp.cacheOrGroupName() + ", part=" + part + ']';
                    part.lock();
                    try {
                        // Loop through all received entries and try to preload them.
                        for (GridCacheEntryInfo entry : e.getValue().infos()) {
                            if (!preloadEntry(node, p, entry, topVer)) {
                                if (log.isDebugEnabled())
                                    log.debug("Got entries for invalid partition during " + "preloading (will skip) [p=" + p + ", entry=" + entry + ']');
                                break;
                            }
                            if (grp.sharedGroup() && (cctx == null || cctx.cacheId() != entry.cacheId()))
                                cctx = ctx.cacheContext(entry.cacheId());
                            if (cctx != null && cctx.statisticsEnabled())
                                cctx.cache().metrics0().onRebalanceKeyReceived();
                        }
                        // then we take ownership.
                        if (last) {
                            top.own(part);
                            fut.partitionDone(nodeId, p);
                            if (log.isDebugEnabled())
                                log.debug("Finished rebalancing partition: " + part);
                        }
                    } finally {
                        part.unlock();
                        part.release();
                    }
                } else {
                    if (last)
                        fut.partitionDone(nodeId, p);
                    if (log.isDebugEnabled())
                        log.debug("Skipping rebalancing partition (state is not MOVING): " + part);
                }
            } else {
                fut.partitionDone(nodeId, p);
                if (log.isDebugEnabled())
                    log.debug("Skipping rebalancing partition (it does not belong on current node): " + p);
            }
        }
        // Only request partitions based on latest topology version.
        for (Integer miss : supply.missed()) {
            if (aff.get(miss).contains(ctx.localNode()))
                fut.partitionMissed(nodeId, miss);
        }
        for (Integer miss : supply.missed()) fut.partitionDone(nodeId, miss);
        GridDhtPartitionDemandMessage d = new GridDhtPartitionDemandMessage(supply.rebalanceId(), supply.topologyVersion(), grp.groupId());
        d.timeout(grp.config().getRebalanceTimeout());
        d.topic(rebalanceTopics.get(topicId));
        if (!topologyChanged(fut) && !fut.isDone()) {
            // Send demand message.
            try {
                ctx.io().sendOrderedMessage(node, rebalanceTopics.get(topicId), d.convertIfNeeded(node.version()), grp.ioPolicy(), grp.config().getRebalanceTimeout());
            } catch (ClusterTopologyCheckedException e) {
                if (log.isDebugEnabled()) {
                    log.debug("Node left during rebalancing [grp=" + grp.cacheOrGroupName() + ", node=" + node.id() + ", msg=" + e.getMessage() + ']');
                }
            }
        }
    } catch (IgniteSpiException | IgniteCheckedException e) {
        LT.error(log, e, "Error during rebalancing [grp=" + grp.cacheOrGroupName() + ", srcNode=" + node.id() + ", err=" + e + ']');
    }
}
Also used : ClusterNode(org.apache.ignite.cluster.ClusterNode) GridCacheEntryInfo(org.apache.ignite.internal.processors.cache.GridCacheEntryInfo) AffinityAssignment(org.apache.ignite.internal.processors.affinity.AffinityAssignment) GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) AffinityTopologyVersion(org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion) GridDhtPartitionTopology(org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionTopology) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) CacheEntryInfoCollection(org.apache.ignite.internal.processors.cache.CacheEntryInfoCollection) GridDhtLocalPartition(org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLocalPartition) IgniteSpiException(org.apache.ignite.spi.IgniteSpiException) Map(java.util.Map) HashMap(java.util.HashMap) ClusterTopologyCheckedException(org.apache.ignite.internal.cluster.ClusterTopologyCheckedException)

Example 62 with GridCacheContext

use of org.apache.ignite.internal.processors.cache.GridCacheContext in project ignite by apache.

the class GridDhtPartitionDemander method awaitClearingAndStartRebalance.

/**
 * Awaits partitions clearing for full partitions and sends initial demand request
 * after all partitions are cleared and safe to consume data.
 *
 * @param fut Rebalance future.
 * @param demandMessage Initial demand message which contains set of full partitions to await.
 * @param initDemandRequestTask Task which sends initial demand request.
 */
private void awaitClearingAndStartRebalance(RebalanceFuture fut, GridDhtPartitionDemandMessage demandMessage, Runnable initDemandRequestTask) {
    Set<Integer> fullPartitions = demandMessage.partitions().fullSet();
    if (fullPartitions.isEmpty()) {
        ctx.kernalContext().closure().runLocalSafe(initDemandRequestTask, true);
        return;
    }
    for (GridCacheContext cctx : grp.caches()) {
        if (cctx.statisticsEnabled()) {
            final CacheMetricsImpl metrics = cctx.cache().metrics0();
            metrics.rebalanceClearingPartitions(fullPartitions.size());
        }
    }
    final AtomicInteger clearingPartitions = new AtomicInteger(fullPartitions.size());
    for (int partId : fullPartitions) {
        if (fut.isDone())
            return;
        GridDhtLocalPartition part = grp.topology().localPartition(partId);
        if (part != null && part.state() == MOVING) {
            part.onClearFinished(f -> {
                // Cancel rebalance if partition clearing was failed.
                if (f.error() != null) {
                    if (!fut.isDone()) {
                        for (GridCacheContext cctx : grp.caches()) {
                            if (cctx.statisticsEnabled()) {
                                final CacheMetricsImpl metrics = cctx.cache().metrics0();
                                metrics.rebalanceClearingPartitions(0);
                            }
                        }
                        log.error("Unable to await partition clearing " + part, f.error());
                        fut.cancel();
                    }
                } else {
                    if (!fut.isDone()) {
                        int existed = clearingPartitions.decrementAndGet();
                        for (GridCacheContext cctx : grp.caches()) {
                            if (cctx.statisticsEnabled()) {
                                final CacheMetricsImpl metrics = cctx.cache().metrics0();
                                metrics.rebalanceClearingPartitions(existed);
                            }
                        }
                        // If all partitions are cleared send initial demand message.
                        if (existed == 0)
                            ctx.kernalContext().closure().runLocalSafe(initDemandRequestTask, true);
                    }
                }
            });
        } else
            clearingPartitions.decrementAndGet();
    }
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) CacheMetricsImpl(org.apache.ignite.internal.processors.cache.CacheMetricsImpl) GridDhtLocalPartition(org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLocalPartition)

Example 63 with GridCacheContext

use of org.apache.ignite.internal.processors.cache.GridCacheContext in project ignite by apache.

the class GridDhtPartitionsExchangeFuture method onDone.

/**
 * {@inheritDoc}
 */
@Override
public boolean onDone(@Nullable AffinityTopologyVersion res, @Nullable Throwable err) {
    if (isDone() || !done.compareAndSet(false, true))
        return false;
    if (log.isInfoEnabled()) {
        log.info("Finish exchange future [startVer=" + initialVersion() + ", resVer=" + res + ", err=" + err + ']');
    }
    assert res != null || err != null;
    if (err == null && !cctx.kernalContext().clientNode() && (serverNodeDiscoveryEvent() || affChangeMsg != null)) {
        for (GridCacheContext cacheCtx : cctx.cacheContexts()) {
            if (!cacheCtx.affinityNode() || cacheCtx.isLocal())
                continue;
            cacheCtx.continuousQueries().flushBackupQueue(res);
        }
    }
    if (err == null) {
        if (centralizedAff || forceAffReassignment) {
            assert !exchCtx.mergeExchanges();
            for (CacheGroupContext grp : cctx.cache().cacheGroups()) {
                if (grp.isLocal())
                    continue;
                boolean needRefresh = false;
                try {
                    needRefresh = grp.topology().initPartitionsWhenAffinityReady(res, this);
                } catch (IgniteInterruptedCheckedException e) {
                    U.error(log, "Failed to initialize partitions.", e);
                }
                if (needRefresh)
                    cctx.exchange().refreshPartitions();
            }
        }
        for (GridCacheContext cacheCtx : cctx.cacheContexts()) {
            GridCacheContext drCacheCtx = cacheCtx.isNear() ? cacheCtx.near().dht().context() : cacheCtx;
            if (drCacheCtx.isDrEnabled()) {
                try {
                    drCacheCtx.dr().onExchange(res, exchId.isLeft());
                } catch (IgniteCheckedException e) {
                    U.error(log, "Failed to notify DR: " + e, e);
                }
            }
        }
        if (serverNodeDiscoveryEvent())
            detectLostPartitions(res);
        Map<Integer, CacheValidation> m = U.newHashMap(cctx.cache().cacheGroups().size());
        for (CacheGroupContext grp : cctx.cache().cacheGroups()) m.put(grp.groupId(), validateCacheGroup(grp, events().lastEvent().topologyNodes()));
        grpValidRes = m;
    }
    if (!cctx.localNode().isClient())
        tryToPerformLocalSnapshotOperation();
    cctx.cache().onExchangeDone(initialVersion(), exchActions, err);
    cctx.exchange().onExchangeDone(res, initialVersion(), err);
    cctx.kernalContext().authentication().onActivate();
    if (exchActions != null && err == null)
        exchActions.completeRequestFutures(cctx);
    if (stateChangeExchange() && err == null)
        cctx.kernalContext().state().onStateChangeExchangeDone(exchActions.stateChangeRequest());
    Map<T2<Integer, Integer>, Long> localReserved = partHistSuppliers.getReservations(cctx.localNodeId());
    if (localReserved != null) {
        for (Map.Entry<T2<Integer, Integer>, Long> e : localReserved.entrySet()) {
            boolean success = cctx.database().reserveHistoryForPreloading(e.getKey().get1(), e.getKey().get2(), e.getValue());
            if (!success) {
                // TODO: how to handle?
                err = new IgniteCheckedException("Could not reserve history");
            }
        }
    }
    cctx.database().releaseHistoryForExchange();
    cctx.database().rebuildIndexesIfNeeded(this);
    if (err == null) {
        for (CacheGroupContext grp : cctx.cache().cacheGroups()) {
            if (!grp.isLocal())
                grp.topology().onExchangeDone(this, grp.affinity().readyAffinity(res), false);
        }
    }
    if (super.onDone(res, err)) {
        if (log.isDebugEnabled())
            log.debug("Completed partition exchange [localNode=" + cctx.localNodeId() + ", exchange= " + this + ", durationFromInit=" + (U.currentTimeMillis() - initTs) + ']');
        initFut.onDone(err == null);
        if (exchCtx != null && exchCtx.events().hasServerLeft()) {
            ExchangeDiscoveryEvents evts = exchCtx.events();
            for (DiscoveryEvent evt : exchCtx.events().events()) {
                if (serverLeftEvent(evt)) {
                    for (CacheGroupContext grp : cctx.cache().cacheGroups()) grp.affinityFunction().removeNode(evt.eventNode().id());
                }
            }
        }
        exchActions = null;
        if (firstDiscoEvt instanceof DiscoveryCustomEvent)
            ((DiscoveryCustomEvent) firstDiscoEvt).customMessage(null);
        if (err == null) {
            cctx.exchange().lastFinishedFuture(this);
            if (exchCtx != null && (exchCtx.events().hasServerLeft() || exchCtx.events().hasServerJoin())) {
                ExchangeDiscoveryEvents evts = exchCtx.events();
                for (DiscoveryEvent evt : exchCtx.events().events()) {
                    if (serverLeftEvent(evt) || serverJoinEvent(evt))
                        logExchange(evt);
                }
            }
        }
        return true;
    }
    return false;
}
Also used : GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) DiscoveryEvent(org.apache.ignite.events.DiscoveryEvent) ExchangeDiscoveryEvents(org.apache.ignite.internal.processors.cache.ExchangeDiscoveryEvents) DiscoveryCustomEvent(org.apache.ignite.internal.events.DiscoveryCustomEvent) IgniteInterruptedCheckedException(org.apache.ignite.internal.IgniteInterruptedCheckedException) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteSystemProperties.getLong(org.apache.ignite.IgniteSystemProperties.getLong) CacheGroupContext(org.apache.ignite.internal.processors.cache.CacheGroupContext) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) T2(org.apache.ignite.internal.util.typedef.T2)

Example 64 with GridCacheContext

use of org.apache.ignite.internal.processors.cache.GridCacheContext in project ignite by apache.

the class GridDhtPartitionsExchangeFuture method distributedExchange.

/**
 * @throws IgniteCheckedException If failed.
 */
private void distributedExchange() throws IgniteCheckedException {
    assert crd != null;
    assert !cctx.kernalContext().clientNode();
    for (CacheGroupContext grp : cctx.cache().cacheGroups()) {
        if (grp.isLocal())
            continue;
        grp.preloader().onTopologyChanged(this);
    }
    cctx.database().releaseHistoryForPreloading();
    // To correctly rebalance when persistence is enabled, it is necessary to reserve history within exchange.
    partHistReserved = cctx.database().reserveHistoryForExchange();
    waitPartitionRelease();
    boolean topChanged = firstDiscoEvt.type() != EVT_DISCOVERY_CUSTOM_EVT || affChangeMsg != null;
    for (GridCacheContext cacheCtx : cctx.cacheContexts()) {
        if (cacheCtx.isLocal() || cacheStopping(cacheCtx.cacheId()))
            continue;
        if (topChanged) {
            // Partition release future is done so we can flush the write-behind store.
            cacheCtx.store().forceFlush();
        }
    }
    if (!exchCtx.mergeExchanges()) {
        for (CacheGroupContext grp : cctx.cache().cacheGroups()) {
            if (grp.isLocal() || cacheGroupStopping(grp.groupId()))
                continue;
            // It is possible affinity is not initialized yet if node joins to cluster.
            if (grp.affinity().lastVersion().topologyVersion() > 0)
                grp.topology().beforeExchange(this, !centralizedAff && !forceAffReassignment, false);
        }
    }
    // It is necessary to run database callback after all topology callbacks, so partition states could be
    // correctly restored from the persistent store.
    cctx.database().beforeExchange(this);
    changeWalModeIfNeeded();
    if (crd.isLocal()) {
        if (remaining.isEmpty())
            onAllReceived(null);
    } else
        sendPartitions(crd);
    initDone();
}
Also used : GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) CacheGroupContext(org.apache.ignite.internal.processors.cache.CacheGroupContext)

Example 65 with GridCacheContext

use of org.apache.ignite.internal.processors.cache.GridCacheContext in project ignite by apache.

the class GridNearGetResponse method prepareMarshal.

/**
 * {@inheritDoc}
 * @param ctx
 */
@Override
public void prepareMarshal(GridCacheSharedContext ctx) throws IgniteCheckedException {
    super.prepareMarshal(ctx);
    GridCacheContext cctx = ctx.cacheContext(cacheId);
    if (entries != null) {
        for (GridCacheEntryInfo info : entries) info.marshal(cctx);
    }
    if (err != null && errBytes == null)
        errBytes = U.marshal(ctx, err);
}
Also used : GridCacheEntryInfo(org.apache.ignite.internal.processors.cache.GridCacheEntryInfo) GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext)

Aggregations

GridCacheContext (org.apache.ignite.internal.processors.cache.GridCacheContext)147 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)37 GridCacheEntryRemovedException (org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException)22 HashMap (java.util.HashMap)21 ClusterNode (org.apache.ignite.cluster.ClusterNode)20 Map (java.util.Map)19 UUID (java.util.UUID)18 KeyCacheObject (org.apache.ignite.internal.processors.cache.KeyCacheObject)18 GridCacheEntryEx (org.apache.ignite.internal.processors.cache.GridCacheEntryEx)16 ArrayList (java.util.ArrayList)15 IgniteException (org.apache.ignite.IgniteException)14 CacheObject (org.apache.ignite.internal.processors.cache.CacheObject)14 List (java.util.List)13 AffinityTopologyVersion (org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion)13 GridCacheVersion (org.apache.ignite.internal.processors.cache.version.GridCacheVersion)13 ClusterTopologyCheckedException (org.apache.ignite.internal.cluster.ClusterTopologyCheckedException)11 ConcurrentMap (java.util.concurrent.ConcurrentMap)10 IgniteTxEntry (org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry)10 GridCacheEntryInfo (org.apache.ignite.internal.processors.cache.GridCacheEntryInfo)9 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)8