/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* 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 org.hawkular.alerts.engine.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hawkular.alerts.engine.impl.PartitionManagerImpl.PartitionEntry;
import org.junit.Test;
/**
* Testing redistribution of buckets on topology changes.
*
* @author Jay Shaughnessy
* @author Lucas Ponce
*/
public class BucketsTest {
@Test
public void emptyOldBuckets() {
PartitionManagerImpl pm = new PartitionManagerImpl();
try {
pm.updateBuckets(null, null);
fail("It should faild with null newMembers");
} catch (Exception expected) {}
try {
pm.updateBuckets(null, new ArrayList<>());
fail("It should faild with empty newMembers");
} catch (Exception expected) {}
List<Integer> members = Arrays.asList(2001, 3002, 4003, 5004);
Map<Integer, Integer> newBuckets = pm.updateBuckets(null, members);
assertEquals(newBuckets.get(0).intValue(), 2001);
assertEquals(newBuckets.get(1).intValue(), 3002);
assertEquals(newBuckets.get(2).intValue(), 4003);
assertEquals(newBuckets.get(3).intValue(), 5004);
}
@Test
public void reassignBuckets() {
PartitionManagerImpl pm = new PartitionManagerImpl();
/*
Old: {0=server0, 1=server1, 2=server2, 3=server3, 4=server4, 5=server5, 6=server6, 7=server7, 8=server8}
Drop server3
New: {0=server0, 1=server1, 2=server2, 3=server8, 4=server4, 5=server5, 6=server6, 7=server7}
*/
Map<Integer, Integer> oldBuckets = new HashMap<>();
oldBuckets.put(0, 1000);
oldBuckets.put(1, 1001);
oldBuckets.put(2, 1002);
oldBuckets.put(3, 1003);
oldBuckets.put(4, 1004);
oldBuckets.put(5, 1005);
oldBuckets.put(6, 1006);
oldBuckets.put(7, 1007);
oldBuckets.put(8, 1008);
List<Integer> members = Arrays.asList(1000, 1001, 1002, 1004, 1005, 1006, 1007, 1008);
Map<Integer, Integer> newBuckets = pm.updateBuckets(oldBuckets, members);
assertEquals(newBuckets.get(0).intValue(), 1000);
assertEquals(newBuckets.get(1).intValue(), 1001);
assertEquals(newBuckets.get(2).intValue(), 1002);
assertEquals(newBuckets.get(3).intValue(), 1008);
assertEquals(newBuckets.get(4).intValue(), 1004);
assertEquals(newBuckets.get(5).intValue(), 1005);
assertEquals(newBuckets.get(6).intValue(), 1006);
assertEquals(newBuckets.get(7).intValue(), 1007);
/*
Old: {0=server0, 1=server1, 2=server2, 3=server8, 4=server4, 5=server5, 6=server6, 7=server7}
Drop server0
New: {0=server7, 1=server1, 2=server2, 3=server8, 4=server4, 5=server5, 6=server6}
*/
oldBuckets = newBuckets;
members = Arrays.asList(1001, 1002, 1004, 1005, 1006, 1007, 1008);
newBuckets = pm.updateBuckets(oldBuckets, members);
assertEquals(newBuckets.get(0).intValue(), 1007);
assertEquals(newBuckets.get(1).intValue(), 1001);
assertEquals(newBuckets.get(2).intValue(), 1002);
assertEquals(newBuckets.get(3).intValue(), 1008);
assertEquals(newBuckets.get(4).intValue(), 1004);
assertEquals(newBuckets.get(5).intValue(), 1005);
assertEquals(newBuckets.get(6).intValue(), 1006);
/*
Old: {0=server7, 1=server1, 2=server2, 3=server8, 4=server4, 5=server5, 6=server6}
Drops server7, server2, server5
New: {0=server4, 1=server1, 2=server6, 3=server8}
*/
oldBuckets = newBuckets;
members = Arrays.asList(1001, 1004, 1006, 1008);
newBuckets = pm.updateBuckets(oldBuckets, members);
assertEquals(newBuckets.get(0).intValue(), 1004);
assertEquals(newBuckets.get(1).intValue(), 1001);
assertEquals(newBuckets.get(2).intValue(), 1006);
assertEquals(newBuckets.get(3).intValue(), 1008);
/*
Worst case
Old: {0=server4, 1=server1, 2=server6, 3=server8}
Drops everything with new nodes
New: {0=new1, 1=new2, 2=new3}
*/
oldBuckets = newBuckets;
members = Arrays.asList(2001, 2002, 2003);
newBuckets = pm.updateBuckets(oldBuckets, members);
assertEquals(newBuckets.get(0).intValue(), 2001);
assertEquals(newBuckets.get(1).intValue(), 2002);
assertEquals(newBuckets.get(2).intValue(), 2003);
/*
Strange case
Old: {0=new1, 1=new2, 2=new3}
Drops new1 and server1 is back
New: {0=server1, 1=new2, 2=new3}
*/
oldBuckets = newBuckets;
members = Arrays.asList(1001, 2002, 2003);
newBuckets = pm.updateBuckets(oldBuckets, members);
assertEquals(newBuckets.get(0).intValue(), 1001);
assertEquals(newBuckets.get(1).intValue(), 2002);
assertEquals(newBuckets.get(2).intValue(), 2003);
/*
Strange case
Old: {0=server1, 1=new2, 2=new3}
Drops new2 and new3 and server2 and server3 are back but in different order
New: {0=server1, 1=server3, 2=server2}
*/
oldBuckets = newBuckets;
members = Arrays.asList(1001, 1003, 1002);
newBuckets = pm.updateBuckets(oldBuckets, members);
assertEquals(newBuckets.get(0).intValue(), 1001);
assertEquals(newBuckets.get(1).intValue(), 1003);
assertEquals(newBuckets.get(2).intValue(), 1002);
/*
Strange case
No changes, but members order is different
Result: bucket should not be affected
*/
oldBuckets = newBuckets;
members = Arrays.asList(1003, 1002, 1001);
newBuckets = pm.updateBuckets(oldBuckets, members);
assertEquals(newBuckets.get(0).intValue(), 1001);
assertEquals(newBuckets.get(1).intValue(), 1003);
assertEquals(newBuckets.get(2).intValue(), 1002);
/*
Normal case
New nodes new1, new2, new2 joining
New: {0=server1, 1=server3, 2=server2, 3=new1, 4=new2, 5=new3}
*/
oldBuckets = newBuckets;
members = Arrays.asList(1003, 1002, 1001, 2001, 2002, 2003);
newBuckets = pm.updateBuckets(oldBuckets, members);
assertEquals(newBuckets.get(0).intValue(), 1001);
assertEquals(newBuckets.get(1).intValue(), 1003);
assertEquals(newBuckets.get(2).intValue(), 1002);
assertEquals(newBuckets.get(3).intValue(), 2001);
assertEquals(newBuckets.get(4).intValue(), 2002);
assertEquals(newBuckets.get(5).intValue(), 2003);
}
@Test
public void distributeLocalPartitions() {
PartitionManagerImpl pm = new PartitionManagerImpl();
PartitionEntry[] entries = new PartitionEntry[10];
Map<PartitionEntry, Integer> previous = new HashMap<>();
Map<PartitionEntry, Integer> current = new HashMap<>();
for (int i = 0; i < entries.length; i++) {
entries[i] = new PartitionEntry("tenant", "t" + i);
previous.put(entries[i], 1);
if (i < 4) {
current.put(entries[i], 1);
} else {
current.put(entries[i], 2);
}
}
Map<String, Map<String, List<String>>> node1 = pm.getAddedRemovedPartition(previous, current, 1);
Map<String, Map<String, List<String>>> node2 = pm.getAddedRemovedPartition(previous, current, 2);
assertEquals(node1.get("added").size(), 0);
assertEquals(node1.get("removed").get("tenant").size(), 6);
assertEquals(node2.get("removed").size(), 0);
assertEquals(node2.get("added").get("tenant").size(), 6);
}
}