blob: 513817372d26510cef1c8db62c3d98c43b1c465d [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.management.internal.cli.commands;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.Region;
import org.apache.geode.management.internal.i18n.CliStrings;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
import org.apache.geode.test.junit.assertions.CommandResultAssert;
import org.apache.geode.test.junit.assertions.TabularResultModelAssert;
import org.apache.geode.test.junit.rules.GfshCommandRule;
public class RepeatedRebalanceDUnitTest {
private static final String PARENT_REGION = "RepeatedRebalanceTestRegion";
private static final String COLOCATED_REGION_ONE = "RepeatedRebalanceColocatedRegionOne";
private static final String COLOCATED_REGION_TWO = "RepeatedRebalanceColocatedRegionTwo";
private static final String PARTITION_RESOLVER =
"org.apache.geode.management.internal.cli.commands.RepeatedRebalancePartitionResolver";
private static final int TOTAL_NUM_BUCKETS = 48;
private static final int NUM_REDUNDANT_COPIES = 2;
private static final int INITIAL_SERVERS = 4;
private static final int NUMBER_OF_ENTRIES = 30000;
private List<MemberVM> memberList = new ArrayList<>();
private MemberVM locator1;
@Rule
public GfshCommandRule gfsh = new GfshCommandRule();
@Rule
public ClusterStartupRule cluster = new ClusterStartupRule();
@Before
public void before() throws Exception {
locator1 = cluster.startLocatorVM(0);
for (int i = 0; i < INITIAL_SERVERS; ++i) {
memberList.add(cluster.startServerVM(i + 1, locator1.getPort()));
}
gfsh.connectAndVerify(locator1);
gfsh.executeAndAssertThat("create region --name=" + PARENT_REGION
+ " --type=PARTITION --redundant-copies=" + NUM_REDUNDANT_COPIES
+ " --enable-statistics=true "
+ "--recovery-delay=-1 --startup-recovery-delay=-1 --total-num-buckets=" + TOTAL_NUM_BUCKETS
+ " --partition-resolver=" + PARTITION_RESOLVER)
.statusIsSuccess();
gfsh.executeAndAssertThat("create region --name=" + COLOCATED_REGION_ONE
+ " --type=PARTITION --redundant-copies=" + NUM_REDUNDANT_COPIES
+ " --enable-statistics=true "
+ "--recovery-delay=-1 --startup-recovery-delay=-1 --total-num-buckets=" + TOTAL_NUM_BUCKETS
+ " --partition-resolver=" + PARTITION_RESOLVER
+ " --colocated-with=" + PARENT_REGION)
.statusIsSuccess();
gfsh.executeAndAssertThat("create region --name=" + COLOCATED_REGION_TWO
+ " --type=PARTITION --redundant-copies=" + NUM_REDUNDANT_COPIES
+ " --enable-statistics=true "
+ "--recovery-delay=-1 --startup-recovery-delay=-1 --total-num-buckets=" + TOTAL_NUM_BUCKETS
+ " --partition-resolver=" + PARTITION_RESOLVER
+ " --colocated-with=" + COLOCATED_REGION_ONE)
.statusIsSuccess();
}
@Test
public void testSecondRebalanceIsNotNecessaryWithAddedMembers() {
addDataToRegion(NUMBER_OF_ENTRIES);
addOrRestartServers(2, 0);
CommandResultAssert firstRebalance = gfsh.executeAndAssertThat("rebalance").statusIsSuccess();
String parentRegionTableSection = "";
for (int i = 0; i < 3; i++) {
if (firstRebalance.hasTableSection("Table" + i).getActual().getHeader()
.contains(PARENT_REGION)) {
parentRegionTableSection = "Table" + i;
}
}
TabularResultModelAssert parentRegionTable =
firstRebalance.hasTableSection(parentRegionTableSection);
assertRedundancyNotChanged(parentRegionTable);
assertBucketsMoved(parentRegionTable);
assertPrimariesTransfered(parentRegionTable);
CommandResultAssert secondRebalance =
gfsh.executeAndAssertThat("rebalance").statusIsSuccess();
for (int i = 0; i < 3; i++) {
if (secondRebalance.hasTableSection("Table" + i).getActual().getHeader()
.contains(PARENT_REGION)) {
parentRegionTableSection = "Table" + i;
}
}
parentRegionTable = secondRebalance.hasTableSection(parentRegionTableSection);
assertRedundancyNotChanged(parentRegionTable);
assertBucketsNotMoved(parentRegionTable);
assertPrimariesNotTransfered(parentRegionTable);
}
@Test
public void testSecondRebalanceIsNotNecessaryWithAddedAndRestartedMembers() {
addDataToRegion(NUMBER_OF_ENTRIES);
addOrRestartServers(2, 1);
CommandResultAssert firstRebalance = gfsh.executeAndAssertThat("rebalance").statusIsSuccess();
String parentRegionTableSection = "";
for (int i = 0; i < 3; i++) {
if (firstRebalance.hasTableSection("Table" + i).getActual().getHeader()
.contains(PARENT_REGION)) {
parentRegionTableSection = "Table" + i;
}
}
TabularResultModelAssert parentRegionTable =
firstRebalance.hasTableSection(parentRegionTableSection);
assertRedundancyChanged(parentRegionTable);
assertBucketsMoved(parentRegionTable);
assertPrimariesTransfered(parentRegionTable);
CommandResultAssert secondRebalance =
gfsh.executeAndAssertThat("rebalance").statusIsSuccess();
for (int i = 0; i < 3; i++) {
if (secondRebalance.hasTableSection("Table" + i).getActual().getHeader()
.contains(PARENT_REGION)) {
parentRegionTableSection = "Table" + i;
}
}
parentRegionTable = secondRebalance.hasTableSection(parentRegionTableSection);
assertRedundancyNotChanged(parentRegionTable);
assertBucketsNotMoved(parentRegionTable);
assertPrimariesNotTransfered(parentRegionTable);
}
public void addDataToRegion(int entriesToAdd) {
memberList.get(0).invoke(() -> {
Cache cache = ClusterStartupRule.getCache();
assertThat(cache).isNotNull();
Region<String, String> region = cache.getRegion(PARENT_REGION);
Region<String, String> colocatedRegionOne = cache.getRegion(COLOCATED_REGION_ONE);
Region<String, String> colocatedRegionTwo = cache.getRegion(COLOCATED_REGION_TWO);
for (int i = 0; i < entriesToAdd; i++) {
region.put("key" + i, "value" + i);
colocatedRegionOne.put("key" + i, "value" + i);
colocatedRegionTwo.put("key" + i, "value" + i);
}
});
}
public void addOrRestartServers(int serversToAdd, int serversToRestart) {
for (int i = 0; i < serversToAdd; ++i) {
memberList.add(cluster.startServerVM(INITIAL_SERVERS + i, locator1.getPort()));
}
for (int i = 0; i < serversToRestart; ++i) {
if (i < INITIAL_SERVERS && i < memberList.size()) {
memberList.get(i).stop(false);
memberList.remove(i);
memberList.add(i, cluster.startServerVM(i + 1, locator1.getPort()));
}
}
}
// The following methods are provided to allow easier examination of the output of the rebalance
// command
private void assertRedundancyChanged(TabularResultModelAssert tabularResultModelAssert) {
tabularResultModelAssert.hasRow(0).asList()
.contains(CliStrings.REBALANCE__MSG__TOTALBUCKETCREATEBYTES).last().isNotEqualTo("0");
tabularResultModelAssert.hasRow(1).asList()
.contains(CliStrings.REBALANCE__MSG__TOTALBUCKETCREATETIM).last().isNotEqualTo("0");
tabularResultModelAssert.hasRow(2).asList()
.contains(CliStrings.REBALANCE__MSG__TOTALBUCKETCREATESCOMPLETED).last().isNotEqualTo("0");
}
private void assertRedundancyNotChanged(TabularResultModelAssert tabularResultModelAssert) {
tabularResultModelAssert.hasRow(0)
.containsExactly(CliStrings.REBALANCE__MSG__TOTALBUCKETCREATEBYTES, "0");
tabularResultModelAssert.hasRow(1)
.containsExactly(CliStrings.REBALANCE__MSG__TOTALBUCKETCREATETIM, "0");
tabularResultModelAssert.hasRow(2)
.containsExactly(CliStrings.REBALANCE__MSG__TOTALBUCKETCREATESCOMPLETED, "0");
}
private void assertBucketsMoved(TabularResultModelAssert tabularResultModelAssert) {
tabularResultModelAssert.hasRow(3).asList()
.contains(CliStrings.REBALANCE__MSG__TOTALBUCKETTRANSFERBYTES).last().isNotEqualTo("0");
tabularResultModelAssert.hasRow(4).asList()
.contains(CliStrings.REBALANCE__MSG__TOTALBUCKETTRANSFERTIME).last().isNotEqualTo("0");
tabularResultModelAssert.hasRow(5).asList()
.contains(CliStrings.REBALANCE__MSG__TOTALBUCKETTRANSFERSCOMPLETED).last()
.isNotEqualTo("0");
}
private void assertBucketsNotMoved(TabularResultModelAssert tabularResultModelAssert) {
tabularResultModelAssert.hasRow(3)
.containsExactly(CliStrings.REBALANCE__MSG__TOTALBUCKETTRANSFERBYTES, "0");
tabularResultModelAssert.hasRow(4)
.containsExactly(CliStrings.REBALANCE__MSG__TOTALBUCKETTRANSFERTIME, "0");
tabularResultModelAssert.hasRow(5)
.containsExactly(CliStrings.REBALANCE__MSG__TOTALBUCKETTRANSFERSCOMPLETED, "0");
}
private void assertPrimariesTransfered(TabularResultModelAssert tabularResultModelAssert) {
tabularResultModelAssert.hasRow(6).asList()
.contains(CliStrings.REBALANCE__MSG__TOTALPRIMARYTRANSFERTIME).last().isNotEqualTo("0");
tabularResultModelAssert.hasRow(7).asList()
.contains(CliStrings.REBALANCE__MSG__TOTALPRIMARYTRANSFERSCOMPLETED).last()
.isNotEqualTo("0");
}
private void assertPrimariesNotTransfered(TabularResultModelAssert tabularResultModelAssert) {
tabularResultModelAssert.hasRow(6)
.containsExactly(CliStrings.REBALANCE__MSG__TOTALPRIMARYTRANSFERTIME, "0");
tabularResultModelAssert.hasRow(7)
.containsExactly(CliStrings.REBALANCE__MSG__TOTALPRIMARYTRANSFERSCOMPLETED, "0");
}
}