blob: 8feb39e5e818e0f8c64edb28551ede160614433a [file] [log] [blame]
/*
* 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.affinity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
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 org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.internal.util.typedef.internal.S;
/**
* Cached affinity calculations.
*
* Deprecated GridAffinityAssignment doesn't support versioning.
* Use GridAffinityAssignmentV2 instead.
*/
@Deprecated
@SuppressWarnings("ForLoopReplaceableByForEach")
public class GridAffinityAssignment implements AffinityAssignment, Serializable {
/** */
private static final long serialVersionUID = 0L;
/** Topology version. */
private final AffinityTopologyVersion topVer;
/** Collection of calculated affinity nodes. */
private List<List<ClusterNode>> assignment;
/** Map of primary node partitions. */
private final Map<UUID, Set<Integer>> primary;
/** Map of backup node partitions. */
private final Map<UUID, Set<Integer>> backup;
/** Assignment node IDs */
private transient volatile List<HashSet<UUID>> assignmentIds;
/** Nodes having primary or backup partition assignments. */
private transient volatile Set<ClusterNode> nodes;
/** Nodes having primary partitions assignments. */
private transient volatile Set<ClusterNode> primaryPartsNodes;
/** */
private transient List<List<ClusterNode>> idealAssignment;
/**
* Constructs cached affinity calculations item.
*
* @param topVer Topology version.
*/
GridAffinityAssignment(AffinityTopologyVersion topVer) {
this.topVer = topVer;
primary = new HashMap<>();
backup = new HashMap<>();
}
/**
* @param topVer Topology version.
* @param assignment Assignment.
* @param idealAssignment Ideal assignment.
*/
GridAffinityAssignment(AffinityTopologyVersion topVer,
List<List<ClusterNode>> assignment,
List<List<ClusterNode>> idealAssignment) {
assert topVer != null;
assert assignment != null;
assert idealAssignment != null;
this.topVer = topVer;
this.assignment = assignment;
this.idealAssignment = idealAssignment.equals(assignment) ? assignment : idealAssignment;
primary = new HashMap<>();
backup = new HashMap<>();
initPrimaryBackupMaps();
}
/**
* @param topVer Topology version.
* @param aff Assignment to copy from.
*/
GridAffinityAssignment(AffinityTopologyVersion topVer, GridAffinityAssignment aff) {
this.topVer = topVer;
assignment = aff.assignment;
idealAssignment = aff.idealAssignment;
primary = aff.primary;
backup = aff.backup;
}
/**
* @return Affinity assignment computed by affinity function.
*/
@Override public List<List<ClusterNode>> idealAssignment() {
return idealAssignment;
}
/**
* @return Affinity assignment.
*/
@Override public List<List<ClusterNode>> assignment() {
return assignment;
}
/**
* @return Topology version.
*/
@Override public AffinityTopologyVersion topologyVersion() {
return topVer;
}
/**
* Get affinity nodes for partition.
*
* @param part Partition.
* @return Affinity nodes.
*/
@Override public List<ClusterNode> get(int part) {
assert part >= 0 && part < assignment.size() : "Affinity partition is out of range" +
" [part=" + part + ", partitions=" + assignment.size() + ']';
return assignment.get(part);
}
/**
* Get affinity node IDs for partition.
*
* @param part Partition.
* @return Affinity nodes IDs.
*/
@Override public HashSet<UUID> getIds(int part) {
assert part >= 0 && part < assignment.size() : "Affinity partition is out of range" +
" [part=" + part + ", partitions=" + assignment.size() + ']';
List<HashSet<UUID>> assignmentIds0 = assignmentIds;
if (assignmentIds0 == null) {
assignmentIds0 = new ArrayList<>();
for (List<ClusterNode> assignmentPart : assignment) {
HashSet<UUID> partIds = new HashSet<>();
for (ClusterNode node : assignmentPart)
partIds.add(node.id());
assignmentIds0.add(partIds);
}
assignmentIds = assignmentIds0;
}
return assignmentIds0.get(part);
}
/** {@inheritDoc} */
@Override public Set<ClusterNode> nodes() {
Set<ClusterNode> res = nodes;
if (res == null) {
res = new HashSet<>();
for (int p = 0; p < assignment.size(); p++) {
List<ClusterNode> nodes = assignment.get(p);
if (!nodes.isEmpty())
res.addAll(nodes);
}
nodes = res;
}
return res;
}
/** {@inheritDoc} */
@Override public Set<ClusterNode> primaryPartitionNodes() {
Set<ClusterNode> res = primaryPartsNodes;
if (res == null) {
res = new HashSet<>();
for (int p = 0; p < assignment.size(); p++) {
List<ClusterNode> nodes = assignment.get(p);
if (!nodes.isEmpty())
res.add(nodes.get(0));
}
primaryPartsNodes = res;
}
return res;
}
/**
* Get primary partitions for specified node ID.
*
* @param nodeId Node ID to get primary partitions for.
* @return Primary partitions for specified node ID.
*/
@Override public Set<Integer> primaryPartitions(UUID nodeId) {
Set<Integer> set = primary.get(nodeId);
return set == null ? Collections.<Integer>emptySet() : set;
}
/**
* Get backup partitions for specified node ID.
*
* @param nodeId Node ID to get backup partitions for.
* @return Backup partitions for specified node ID.
*/
@Override public Set<Integer> backupPartitions(UUID nodeId) {
Set<Integer> set = backup.get(nodeId);
return set == null ? Collections.<Integer>emptySet() : set;
}
/** {@inheritDoc} */
@Override public Set<Integer> partitionPrimariesDifferentToIdeal() {
return Collections.emptySet();
}
/**
* Initializes primary and backup maps.
*/
private void initPrimaryBackupMaps() {
// Temporary mirrors with modifiable partition's collections.
Map<UUID, Set<Integer>> tmpPrm = new HashMap<>();
Map<UUID, Set<Integer>> tmpBkp = new HashMap<>();
for (int partsCnt = assignment.size(), p = 0; p < partsCnt; p++) {
// Use the first node as primary, other - backups.
Map<UUID, Set<Integer>> tmp = tmpPrm;
Map<UUID, Set<Integer>> map = primary;
for (ClusterNode node : assignment.get(p)) {
UUID id = node.id();
Set<Integer> set = tmp.get(id);
if (set == null) {
tmp.put(id, set = new HashSet<>());
map.put(id, Collections.unmodifiableSet(set));
}
set.add(p);
// Use the first node as primary, other - backups.
tmp = tmpBkp;
map = backup;
}
}
}
/** {@inheritDoc} */
@Override public int hashCode() {
return topVer.hashCode();
}
/** {@inheritDoc} */
@SuppressWarnings("SimplifiableIfStatement")
@Override public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof AffinityAssignment))
return false;
return topVer.equals(((AffinityAssignment)o).topologyVersion());
}
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(GridAffinityAssignment.class, this, super.toString());
}
}