blob: b783683cf104b0a9831aca4050c625d0b9339060 [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.geode.internal.cache;
import static org.apache.geode.distributed.ConfigurationProperties.REDUNDANCY_ZONE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Properties;
import org.junit.Test;
import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.PartitionAttributes;
import org.apache.geode.cache.PartitionAttributesFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.SerializableCallable;
import org.apache.geode.test.dunit.SerializableRunnable;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase;
public class PartitionedRegionRedundancyZoneDUnitTest extends JUnit4CacheTestCase {
@Override
public final void postTearDownCacheTestCase() throws Exception {
// this makes sure we don't leave anything for the next tests
// Tests that set redundancy zones causes other jvms connected
// to the ds to have "enforce-unique-hosts" set to true.
// See bug 51883.
disconnectAllFromDS();
}
/**
* Test that we don't try to put buckets in the same zone when we don't have enough zones.
*/
@Test
public void testNotEnoughZones() throws Exception {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
VM vm2 = host.getVM(2);
setRedundancyZone(vm0, "A");
setRedundancyZone(vm1, "A");
setRedundancyZone(vm2, "B");
createPR(vm0, 2);
createPR(vm1, 2);
createPR(vm2, 2);
createData(vm0, 0, 6, "A");
int vm0Count = getBucketCount(vm0);
int vm1Count = getBucketCount(vm1);
int vm2Count = getBucketCount(vm2);
String counts = "vm0=" + vm0Count + ",vm1=" + vm1Count + ",vm2=" + vm2Count;
// assert zone A has only 1 copy of each bucket and zone B has
// only one copy of each bucket.
assertEquals(counts, 6, vm0Count + vm1Count);
assertEquals(counts, 6, vm2Count);
// Ideally, vm0 and vm1 would each have three buckets. However, due
// to the way we place buckets, they may be off by one. The problem is that
// we try to balance primaries first, rather than bucket counts, during bucket placement
// When trying place the last primary bucket, we may have already placed 2 redundant
// buckets on vm0 or vm1. At that point we will add another bucket to that
// member to bring it's primary count up to two.
assertTrue(counts, vm0Count >= 2 && vm1Count >= 2);
}
protected void checkBucketCount(VM vm0, final int numLocalBuckets) {
vm0.invoke(new SerializableRunnable("checkLowRedundancy") {
@Override
public void run() {
Cache cache = getCache();
PartitionedRegion region = (PartitionedRegion) cache.getRegion("region1");
assertEquals(numLocalBuckets, region.getLocalBucketsListTestOnly().size());
}
});
}
protected int getBucketCount(VM vm0) {
return (Integer) vm0.invoke(new SerializableCallable("checkLowRedundancy") {
@Override
public Object call() {
Cache cache = getCache();
PartitionedRegion region = (PartitionedRegion) cache.getRegion("region1");
return region.getLocalBucketsListTestOnly().size();
}
});
}
protected DistributedMember createPR(VM vm, int redundancy) throws Exception {
SerializableCallable createPrRegion = new SerializableCallable("createRegion") {
@Override
public Object call() {
Cache cache = getCache();
AttributesFactory attr = new AttributesFactory();
PartitionAttributesFactory paf = new PartitionAttributesFactory();
paf.setRedundantCopies(1);
PartitionAttributes prAttr = paf.create();
attr.setPartitionAttributes(prAttr);
cache.createRegion("region1", attr.create());
return cache.getDistributedSystem().getDistributedMember();
}
};
return (DistributedMember) vm.invoke(createPrRegion);
}
protected DistributedMember setRedundancyZone(VM vm, final String zone) {
return (DistributedMember) vm.invoke(new SerializableCallable("set redundancy zone") {
@Override
public Object call() {
Properties props = new Properties();
props.setProperty(REDUNDANCY_ZONE, zone);
DistributedSystem system = getSystem(props);
return system.getDistributedMember();
}
});
}
protected void createData(VM vm, final int startKey, final int endKey, final String value) {
createData(vm, startKey, endKey, value, "region1");
}
protected void createData(VM vm, final int startKey, final int endKey, final String value,
final String regionName) {
SerializableRunnable createData = new SerializableRunnable("createData") {
@Override
public void run() {
Cache cache = getCache();
Region region = cache.getRegion(regionName);
for (int i = startKey; i < endKey; i++) {
region.put(i, value);
}
}
};
vm.invoke(createData);
}
}