/*
* 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.managers.discovery;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.internal.util.GridConcurrentHashSet;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.P1;
import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.jetbrains.annotations.Nullable;
/**
*
*/
public class DiscoCache {
/** Local node. */
private final ClusterNode loc;
/** Remote nodes. */
private final List<ClusterNode> rmtNodes;
/** All nodes. */
private final List<ClusterNode> allNodes;
/** All server nodes. */
private final List<ClusterNode> srvNodes;
/** Daemon nodes. */
private final List<ClusterNode> daemonNodes;
/** All server nodes. */
private final List<ClusterNode> srvNodesWithCaches;
/** All nodes with at least one cache configured. */
@GridToStringInclude
private final List<ClusterNode> allNodesWithCaches;
/** All remote nodes with at least one cache configured. */
@GridToStringInclude
private final List<ClusterNode> rmtNodesWithCaches;
/** Cache nodes by cache name. */
@GridToStringInclude
private final Map<Integer, List<ClusterNode>> allCacheNodes;
/** Affinity cache nodes by cache name. */
@GridToStringInclude
private final Map<Integer, List<ClusterNode>> affCacheNodes;
/** Node map. */
private final Map<UUID, ClusterNode> nodeMap;
/** Caches where at least one node has near cache enabled. */
@GridToStringInclude
private final Set<Integer> nearEnabledCaches;
/** Alive nodes. */
private final Set<UUID> alives = new GridConcurrentHashSet<>();
/**
* @param loc Local node.
* @param rmtNodes Remote nodes.
* @param allNodes All nodes.
* @param srvNodes Server nodes.
* @param daemonNodes Daemon nodes.
* @param srvNodesWithCaches Server nodes with at least one cache configured.
* @param allNodesWithCaches All nodes with at least one cache configured.
* @param rmtNodesWithCaches Remote nodes with at least one cache configured.
* @param allCacheNodes Cache nodes by cache name.
* @param affCacheNodes Affinity cache nodes by cache name.
* @param nodeMap Node map.
* @param nearEnabledCaches Caches where at least one node has near cache enabled.
* @param alives Alive nodes.
*/
DiscoCache(ClusterNode loc,
List<ClusterNode> rmtNodes,
List<ClusterNode> allNodes,
List<ClusterNode> srvNodes,
List<ClusterNode> daemonNodes,
List<ClusterNode> srvNodesWithCaches,
List<ClusterNode> allNodesWithCaches,
List<ClusterNode> rmtNodesWithCaches,
Map<Integer, List<ClusterNode>> allCacheNodes,
Map<Integer, List<ClusterNode>> affCacheNodes,
Map<UUID, ClusterNode> nodeMap,
Set<Integer> nearEnabledCaches,
Set<UUID> alives) {
this.loc = loc;
this.rmtNodes = rmtNodes;
this.allNodes = allNodes;
this.srvNodes = srvNodes;
this.daemonNodes = daemonNodes;
this.srvNodesWithCaches = srvNodesWithCaches;
this.allNodesWithCaches = allNodesWithCaches;
this.rmtNodesWithCaches = rmtNodesWithCaches;
this.allCacheNodes = allCacheNodes;
this.affCacheNodes = affCacheNodes;
this.nodeMap = nodeMap;
this.nearEnabledCaches = nearEnabledCaches;
this.alives.addAll(alives);
}
/** @return Local node. */
public ClusterNode localNode() {
return loc;
}
/** @return Remote nodes. */
public List<ClusterNode> remoteNodes() {
return rmtNodes;
}
/** @return All nodes. */
public List<ClusterNode> allNodes() {
return allNodes;
}
/** @return Server nodes. */
public List<ClusterNode> serverNodes() {
return srvNodes;
}
/** @return Daemon nodes. */
public List<ClusterNode> daemonNodes() {
return daemonNodes;
}
/** @return Server nodes with at least one cache configured. */
public List<ClusterNode> serverNodesWithCaches() {
return srvNodesWithCaches;
}
/**
* Gets all remote nodes that have at least one cache configured.
*
* @return Collection of nodes.
*/
public List<ClusterNode> remoteNodesWithCaches() {
return rmtNodesWithCaches;
}
/**
* Gets collection of nodes with at least one cache configured.
*
* @return Collection of nodes.
*/
public List<ClusterNode> allNodesWithCaches() {
return allNodesWithCaches;
}
/**
* Gets collection of server nodes with at least one cache configured.
*
* @return Collection of nodes.
*/
public Collection<ClusterNode> aliveServerNodes() {
return F.view(serverNodes(), new P1<ClusterNode>() {
@Override public boolean apply(ClusterNode node) {
return alives.contains(node.id());
}
});
}
/**
* Gets collection of server nodes with at least one cache configured.
*
* @return Collection of nodes.
*/
public Collection<ClusterNode> aliveServerNodesWithCaches() {
return F.view(serverNodesWithCaches(), new P1<ClusterNode>() {
@Override public boolean apply(ClusterNode node) {
return alives.contains(node.id());
}
});
}
/**
* @return Oldest alive server node.
*/
public @Nullable ClusterNode oldestAliveServerNode(){
Iterator<ClusterNode> it = aliveServerNodes().iterator();
return it.hasNext() ? it.next() : null;
}
/**
* @return Oldest alive server node with at least one cache configured.
*/
public @Nullable ClusterNode oldestAliveServerNodeWithCache(){
Iterator<ClusterNode> it = aliveServerNodesWithCaches().iterator();
return it.hasNext() ? it.next() : null;
}
/**
* Gets all nodes that have cache with given name.
*
* @param cacheName Cache name.
* @return Collection of nodes.
*/
public List<ClusterNode> cacheNodes(@Nullable String cacheName) {
return cacheNodes(CU.cacheId(cacheName));
}
/**
* Gets all nodes that have cache with given ID.
*
* @param cacheId Cache ID.
* @return Collection of nodes.
*/
public List<ClusterNode> cacheNodes(Integer cacheId) {
return emptyIfNull(allCacheNodes.get(cacheId));
}
/**
* Gets all nodes that have cache with given ID and should participate in affinity calculation. With
* partitioned cache nodes with near-only cache do not participate in affinity node calculation.
*
* @param cacheName Cache name.
* @return Collection of nodes.
*/
public List<ClusterNode> cacheAffinityNodes(@Nullable String cacheName) {
return cacheAffinityNodes(CU.cacheId(cacheName));
}
/**
* Gets all nodes that have cache with given ID and should participate in affinity calculation. With
* partitioned cache nodes with near-only cache do not participate in affinity node calculation.
*
* @param cacheId Cache ID.
* @return Collection of nodes.
*/
public List<ClusterNode> cacheAffinityNodes(int cacheId) {
return emptyIfNull(affCacheNodes.get(cacheId));
}
/**
* Checks if cache with given ID has at least one node with near cache enabled.
*
* @param cacheId Cache ID.
* @return {@code True} if cache with given name has at least one node with near cache enabled.
*/
public boolean hasNearCache(int cacheId) {
return nearEnabledCaches.contains(cacheId);
}
/**
* @param id Node ID.
* @return Node.
*/
public @Nullable ClusterNode node(UUID id) {
return nodeMap.get(id);
}
/**
* Removes left node from alives lists.
*
* @param rmvd Removed node.
*/
public void updateAlives(ClusterNode rmvd) {
alives.remove(rmvd.id());
}
/**
* Removes left nodes from cached alives lists.
*
* @param discovery Discovery manager.
*/
public void updateAlives(GridDiscoveryManager discovery) {
for (UUID alive : alives) {
if (!discovery.alive(alive))
alives.remove(alive);
}
}
/**
* @param nodes Cluster nodes.
* @return Empty collection if nodes list is {@code null}
*/
private List<ClusterNode> emptyIfNull(List<ClusterNode> nodes) {
return nodes == null ? Collections.<ClusterNode>emptyList() : nodes;
}
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(DiscoCache.class, this);
}
}