/*
* Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved.
*
* Licensed 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 com.hazelcast.test;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.instance.Node;
import com.hazelcast.internal.partition.NonFragmentedServiceNamespace;
import com.hazelcast.internal.partition.InternalPartition;
import com.hazelcast.internal.partition.InternalPartitionService;
import com.hazelcast.internal.partition.impl.InternalPartitionServiceImpl;
import com.hazelcast.internal.partition.impl.PartitionReplicaManager;
import com.hazelcast.internal.partition.impl.PartitionServiceState;
import com.hazelcast.internal.partition.impl.ReplicaFragmentSyncInfo;
import com.hazelcast.nio.Address;
import com.hazelcast.spi.ServiceNamespace;
import com.hazelcast.spi.impl.PartitionSpecificRunnable;
import com.hazelcast.spi.partition.IPartition;
import com.hazelcast.util.scheduler.ScheduledEntry;
import org.junit.Assert;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
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.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static com.hazelcast.instance.TestUtil.getNode;
import static com.hazelcast.internal.partition.InternalPartition.MAX_REPLICA_COUNT;
public class TestPartitionUtils {
private TestPartitionUtils() {
}
public static PartitionServiceState getPartitionServiceState(HazelcastInstance instance) {
return getPartitionServiceState(getNode(instance));
}
public static PartitionServiceState getPartitionServiceState(Node node) {
if (node == null) {
return PartitionServiceState.SAFE;
}
InternalPartitionServiceImpl partitionService = (InternalPartitionServiceImpl) node.getPartitionService();
return partitionService.getPartitionReplicaStateChecker().getPartitionServiceState();
}
// TODO: returning only default replica versions
public static Map<Integer, long[]> getAllReplicaVersions(List<HazelcastInstance> instances) throws InterruptedException {
Map<Integer, long[]> replicaVersions = new HashMap<Integer, long[]>();
for (HazelcastInstance instance : instances) {
collectOwnedReplicaVersions(getNode(instance), replicaVersions);
}
return replicaVersions;
}
// TODO: returning only default replica versions
public static Map<Integer, long[]> getOwnedReplicaVersions(Node node) throws InterruptedException {
Map<Integer, long[]> ownedReplicaVersions = new HashMap<Integer, long[]>();
collectOwnedReplicaVersions(node, ownedReplicaVersions);
return ownedReplicaVersions;
}
// TODO: using only default replica versions
private static void collectOwnedReplicaVersions(Node node, Map<Integer, long[]> replicaVersions) throws InterruptedException {
InternalPartitionService partitionService = node.getPartitionService();
Address nodeAddress = node.getThisAddress();
for (IPartition partition : partitionService.getPartitions()) {
if (nodeAddress.equals(partition.getOwnerOrNull())) {
int partitionId = partition.getPartitionId();
replicaVersions.put(partitionId, getDefaultReplicaVersions(node, partitionId));
}
}
}
// TODO: returning only default replica versions
public static long[] getDefaultReplicaVersions(Node node, int partitionId) throws InterruptedException {
return getPartitionReplicaVersionsView(node, partitionId).getVersions().get(NonFragmentedServiceNamespace.INSTANCE);
}
public static PartitionReplicaVersionsView getPartitionReplicaVersionsView(Node node, int partitionId)
throws InterruptedException {
GetReplicaVersionsRunnable runnable = new GetReplicaVersionsRunnable(node, partitionId);
node.getNodeEngine().getOperationService().execute(runnable);
return runnable.getReplicaVersions();
}
public static List<ReplicaFragmentSyncInfo> getOngoingReplicaSyncRequests(HazelcastInstance instance) {
return getOngoingReplicaSyncRequests(getNode(instance));
}
public static List<ReplicaFragmentSyncInfo> getOngoingReplicaSyncRequests(Node node) {
InternalPartitionServiceImpl partitionService = (InternalPartitionServiceImpl) node.getPartitionService();
return partitionService.getOngoingReplicaSyncRequests();
}
public static List<ScheduledEntry<ReplicaFragmentSyncInfo, Void>> getScheduledReplicaSyncRequests(HazelcastInstance instance) {
return getScheduledReplicaSyncRequests(getNode(instance));
}
public static List<ScheduledEntry<ReplicaFragmentSyncInfo, Void>> getScheduledReplicaSyncRequests(Node node) {
InternalPartitionServiceImpl partitionService = (InternalPartitionServiceImpl) node.getPartitionService();
return partitionService.getScheduledReplicaSyncRequests();
}
public static Map<Integer, List<Address>> getAllReplicaAddresses(List<HazelcastInstance> instances) {
if (instances.isEmpty()) {
return Collections.emptyMap();
}
for (HazelcastInstance instance : instances) {
Node node = getNode(instance);
if (node != null && node.isMaster()) {
return getAllReplicaAddresses(node);
}
}
return Collections.emptyMap();
}
public static Map<Integer, List<Address>> getAllReplicaAddresses(HazelcastInstance instance) {
return getAllReplicaAddresses(getNode(instance));
}
public static Map<Integer, List<Address>> getAllReplicaAddresses(Node node) {
Map<Integer, List<Address>> allReplicaAddresses = new HashMap<Integer, List<Address>>();
InternalPartitionService partitionService = node.getPartitionService();
for (int partitionId = 0; partitionId < partitionService.getPartitionCount(); partitionId++) {
allReplicaAddresses.put(partitionId, getReplicaAddresses(node, partitionId));
}
return allReplicaAddresses;
}
public static List<Address> getReplicaAddresses(HazelcastInstance instance, int partitionId) {
return getReplicaAddresses(getNode(instance), partitionId);
}
public static List<Address> getReplicaAddresses(Node node, int partitionId) {
List<Address> replicaAddresses = new ArrayList<Address>();
InternalPartitionService partitionService = node.getPartitionService();
InternalPartition partition = partitionService.getPartition(partitionId);
for (int i = 0; i < MAX_REPLICA_COUNT; i++) {
replicaAddresses.add(partition.getReplicaAddress(i));
}
return replicaAddresses;
}
private static class GetReplicaVersionsRunnable implements PartitionSpecificRunnable {
private final CountDownLatch latch = new CountDownLatch(1);
private final Node node;
private final int partitionId;
private PartitionReplicaVersionsView replicaVersions;
GetReplicaVersionsRunnable(Node node, int partitionId) {
this.node = node;
this.partitionId = partitionId;
}
@Override
public int getPartitionId() {
return partitionId;
}
@Override
public void run() {
InternalPartitionService partitionService = node.nodeEngine.getPartitionService();
PartitionReplicaManager replicaManager =
(PartitionReplicaManager) partitionService.getPartitionReplicaVersionManager();
Collection<ServiceNamespace> namespaces = replicaManager.getNamespaces(partitionId);
Map<ServiceNamespace, long[]> versionMap = new HashMap<ServiceNamespace, long[]>(namespaces.size());
Set<ServiceNamespace> dirty = new HashSet<ServiceNamespace>();
for (ServiceNamespace ns : namespaces) {
long[] originalVersions = replicaManager.getPartitionReplicaVersions(partitionId, ns);
long[] versions = Arrays.copyOf(originalVersions, originalVersions.length);
versionMap.put(ns, versions);
if (replicaManager.isPartitionReplicaVersionDirty(partitionId, ns)) {
dirty.add(ns);
}
}
replicaVersions = new PartitionReplicaVersionsView(versionMap, dirty);
latch.countDown();
}
private void await() throws InterruptedException {
Assert.assertTrue("GetReplicaVersionsRunnable is not executed!", latch.await(1, TimeUnit.MINUTES));
}
PartitionReplicaVersionsView getReplicaVersions() throws InterruptedException {
await();
return replicaVersions;
}
}
public static class PartitionReplicaVersionsView {
private final Map<ServiceNamespace, long[]> versions;
private final Set<ServiceNamespace> dirty;
PartitionReplicaVersionsView(Map<ServiceNamespace, long[]> replicaVersions, Set<ServiceNamespace> dirty) {
this.versions = replicaVersions;
this.dirty = dirty;
}
public Map<ServiceNamespace, long[]> getVersions() {
return versions;
}
public boolean isDirty(ServiceNamespace ns) {
return dirty.contains(ns);
}
}
}