/* * 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.testframework.junits.multijvm; import java.util.Collection; import java.util.Map; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCompute; import org.apache.ignite.cache.affinity.Affinity; import org.apache.ignite.cluster.ClusterNode; import org.apache.ignite.lang.IgniteCallable; import org.apache.ignite.resources.IgniteInstanceResource; import org.jetbrains.annotations.Nullable; /** * Proxy class for affinity at another JVM. */ @SuppressWarnings("TransientFieldInNonSerializableClass") public class AffinityProcessProxy<K> implements Affinity<K> { /** Compute. */ private final transient IgniteCompute compute; /** Cache name. */ private final String cacheName; /** * @param cacheName Cache name. * @param proxy Ignite process proxy. */ public AffinityProcessProxy(String cacheName, IgniteProcessProxy proxy) { this.cacheName = cacheName; this.compute = proxy.remoteCompute(); } /** {@inheritDoc} */ @Override public int partitions() { return compute.call(new PartitionsTask(cacheName)); } /** {@inheritDoc} */ @Override public int partition(K key) { return compute.call(new PartitionTask<>(cacheName, key)); } /** {@inheritDoc} */ @Override public boolean isPrimary(ClusterNode n, K key) { return compute.call(new PrimaryOrBackupNodeTask<>(cacheName, key, n, true, false)); } /** {@inheritDoc} */ @Override public boolean isBackup(ClusterNode n, K key) { return compute.call(new PrimaryOrBackupNodeTask<>(cacheName, key, n, false, true)); } /** {@inheritDoc} */ @Override public boolean isPrimaryOrBackup(ClusterNode n, K key) { return compute.call(new PrimaryOrBackupNodeTask<>(cacheName, key, n, true, true)); } /** {@inheritDoc} */ @Override public int[] primaryPartitions(ClusterNode n) { return compute.call(new GetPartitionsTask(cacheName, n, true, false)); } /** {@inheritDoc} */ @Override public int[] backupPartitions(ClusterNode n) { return compute.call(new GetPartitionsTask(cacheName, n, false, true)); } /** {@inheritDoc} */ @Override public int[] allPartitions(ClusterNode n) { return compute.call(new GetPartitionsTask(cacheName, n, true, true)); } /** {@inheritDoc} */ @Override public Object affinityKey(K key) { return compute.call(new AffinityKeyTask<>(cacheName, key)); } /** {@inheritDoc} */ @Override public Map<ClusterNode, Collection<K>> mapKeysToNodes(Collection<? extends K> keys) { return compute.call(new MapKeysToNodesTask<>(cacheName, keys)); } /** {@inheritDoc} */ @Nullable @Override public ClusterNode mapKeyToNode(K key) { return compute.call(new MapKeyToNodeTask<>(cacheName, key)); } /** {@inheritDoc} */ @Override public Collection<ClusterNode> mapKeyToPrimaryAndBackups(K key) { return compute.call(new MapKeyToPrimaryAndBackupsTask<>(cacheName, key)); } /** {@inheritDoc} */ @Override public ClusterNode mapPartitionToNode(int part) { return compute.call(new MapPartitionToNode<>(cacheName, part)); } /** {@inheritDoc} */ @Override public Map<Integer, ClusterNode> mapPartitionsToNodes(Collection<Integer> parts) { return compute.call(new MapPartitionsToNodes<>(cacheName, parts)); } /** {@inheritDoc} */ @Override public Collection<ClusterNode> mapPartitionToPrimaryAndBackups(int part) { return compute.call(new MapPartitionsToPrimaryAndBackupsTask<>(cacheName, part)); } /** * */ private static class PrimaryOrBackupNodeTask<K> extends AffinityTaskAdapter<K, Boolean> { /** Key. */ private final K key; /** Node. */ private final ClusterNode n; /** Primary. */ private final boolean primary; /** Backup. */ private final boolean backup; /** * @param cacheName Cache name. * @param key Key. * @param n N. */ public PrimaryOrBackupNodeTask(String cacheName, K key, ClusterNode n, boolean primary, boolean backup) { super(cacheName); this.key = key; this.n = n; this.primary = primary; this.backup = backup; } /** {@inheritDoc} */ @Override public Boolean call() throws Exception { if (primary && backup) return affinity().isPrimaryOrBackup(n, key); else if (primary) return affinity().isPrimary(n, key); else if (backup) return affinity().isBackup(n, key); else throw new IllegalStateException("primary or backup or both flags should be switched on"); } } /** * */ private static class MapKeyToPrimaryAndBackupsTask<K> extends AffinityTaskAdapter<K, Collection<ClusterNode>> { /** Key. */ private final K key; /** * @param cacheName Cache name. * @param key Key. */ public MapKeyToPrimaryAndBackupsTask(String cacheName, K key) { super(cacheName); this.key = key; } /** {@inheritDoc} */ @Override public Collection<ClusterNode> call() throws Exception { return affinity().mapKeyToPrimaryAndBackups(key); } } /** * */ private static class PartitionsTask extends AffinityTaskAdapter<Void, Integer> { /** * @param cacheName Cache name. */ public PartitionsTask(String cacheName) { super(cacheName); } /** {@inheritDoc} */ @Override public Integer call() throws Exception { return affinity().partitions(); } } /** * */ private static class PartitionTask<K> extends AffinityTaskAdapter<K, Integer> { /** Key. */ private final K key; /** * @param cacheName Cache name. * @param key Key. */ public PartitionTask(String cacheName, K key) { super(cacheName); this.key = key; } /** {@inheritDoc} */ @Override public Integer call() throws Exception { return affinity().partition(key); } } /** * */ private static class GetPartitionsTask extends AffinityTaskAdapter<Void, int[]> { /** Node. */ private final ClusterNode n; /** Primary. */ private final boolean primary; /** Backup. */ private final boolean backup; /** * @param cacheName Cache name. * @param n N. * @param primary Primary. * @param backup Backup. */ public GetPartitionsTask(String cacheName, ClusterNode n, boolean primary, boolean backup) { super(cacheName); this.n = n; this.primary = primary; this.backup = backup; } /** {@inheritDoc} */ @Override public int[] call() throws Exception { if (primary && backup) return affinity().allPartitions(n); else if (primary) return affinity().primaryPartitions(n); else if (backup) return affinity().backupPartitions(n); else throw new IllegalStateException("primary or backup or both flags should be switched on"); } } /** * */ private static class AffinityKeyTask<K> extends AffinityTaskAdapter<K, Object> { /** Key. */ private final K key; /** * @param cacheName Cache name. * @param key Key. */ public AffinityKeyTask(String cacheName, K key) { super(cacheName); this.key = key; } /** {@inheritDoc} */ @Override public Object call() throws Exception { return affinity().affinityKey(key); } } /** * @param <K> */ private static class MapKeysToNodesTask<K> extends AffinityTaskAdapter<K, Map<ClusterNode, Collection<K>>> { /** Keys. */ private final Collection<? extends K> keys; /** * @param cacheName Cache name. * @param keys Keys. */ public MapKeysToNodesTask(String cacheName, Collection<? extends K> keys) { super(cacheName); this.keys = keys; } /** {@inheritDoc} */ @Override public Map<ClusterNode, Collection<K>> call() throws Exception { return affinity().mapKeysToNodes(keys); } } /** * */ private static class MapKeyToNodeTask<K> extends AffinityTaskAdapter<K, ClusterNode> { /** Key. */ private final K key; /** * @param cacheName Cache name. * @param key Key. */ public MapKeyToNodeTask(String cacheName, K key) { super(cacheName); this.key = key; } /** {@inheritDoc} */ @Override public ClusterNode call() throws Exception { return affinity().mapKeyToNode(key); } } /** * */ private static class MapPartitionToNode<K> extends AffinityTaskAdapter<K, ClusterNode> { /** Partition. */ private final int part; /** * @param cacheName Cache name. * @param part Partition. */ public MapPartitionToNode(String cacheName, int part) { super(cacheName); this.part = part; } /** {@inheritDoc} */ @Override public ClusterNode call() throws Exception { return affinity().mapPartitionToNode(part); } } /** * */ private static class MapPartitionsToNodes<K> extends AffinityTaskAdapter<K, Map<Integer, ClusterNode>> { /** Parts. */ private final Collection<Integer> parts; /** * @param cacheName Cache name. * @param parts Parts. */ public MapPartitionsToNodes(String cacheName, Collection<Integer> parts) { super(cacheName); this.parts = parts; } /** {@inheritDoc} */ @Override public Map<Integer, ClusterNode> call() throws Exception { return affinity().mapPartitionsToNodes(parts); } } /** * */ private static class MapPartitionsToPrimaryAndBackupsTask<K> extends AffinityTaskAdapter<K, Collection<ClusterNode>> { /** Partition. */ private final int part; /** * @param cacheName Cache name. * @param part Partition. */ public MapPartitionsToPrimaryAndBackupsTask(String cacheName, int part) { super(cacheName); this.part = part; } /** {@inheritDoc} */ @Override public Collection<ClusterNode> call() throws Exception { return affinity().mapPartitionToPrimaryAndBackups(part); } } /** * */ private abstract static class AffinityTaskAdapter<K, R> implements IgniteCallable<R> { /** Ignite. */ @IgniteInstanceResource protected Ignite ignite; /** Cache name. */ protected final String cacheName; /** * @param cacheName Cache name. */ public AffinityTaskAdapter(String cacheName) { this.cacheName = cacheName; } /** * @return Affinity. */ protected Affinity<K> affinity() { return ignite.affinity(cacheName); } } }