/**
* 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.hadoop.hbase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.apache.hadoop.hbase.testclassification.SmallTests;
import org.junit.Test;
import org.junit.experimental.categories.Category;
@Category(SmallTests.class)
public class TestRegionLocations {
ServerName sn0 = ServerName.valueOf("host0", 10, 10);
ServerName sn1 = ServerName.valueOf("host1", 10, 10);
ServerName sn2 = ServerName.valueOf("host2", 10, 10);
ServerName sn3 = ServerName.valueOf("host3", 10, 10);
HRegionInfo info0 = hri(0);
HRegionInfo info1 = hri(1);
HRegionInfo info2 = hri(2);
HRegionInfo info9 = hri(9);
@Test
public void testSizeMethods() {
RegionLocations list = new RegionLocations();
assertTrue(list.isEmpty());
assertEquals(0, list.size());
assertEquals(0, list.numNonNullElements());
list = hrll((HRegionLocation)null);
assertTrue(list.isEmpty());
assertEquals(1, list.size());
assertEquals(0, list.numNonNullElements());
HRegionInfo info0 = hri(0);
list = hrll(hrl(info0, null));
assertTrue(list.isEmpty());
assertEquals(1, list.size());
assertEquals(0, list.numNonNullElements());
HRegionInfo info9 = hri(9);
list = hrll(hrl(info9, null));
assertTrue(list.isEmpty());
assertEquals(10, list.size());
assertEquals(0, list.numNonNullElements());
list = hrll(hrl(info0, null), hrl(info9, null));
assertTrue(list.isEmpty());
assertEquals(10, list.size());
assertEquals(0, list.numNonNullElements());
}
private HRegionInfo hri(int replicaId) {
TableName table = TableName.valueOf("table");
byte[] startKey = HConstants.EMPTY_START_ROW;
byte[] endKey = HConstants.EMPTY_END_ROW;
long regionId = System.currentTimeMillis();
HRegionInfo info = new HRegionInfo(table, startKey, endKey, false, regionId, replicaId);
return info;
}
private HRegionLocation hrl(HRegionInfo hri, ServerName sn) {
return new HRegionLocation(hri, sn);
}
private HRegionLocation hrl(HRegionInfo hri, ServerName sn, long seqNum) {
return new HRegionLocation(hri, sn, seqNum);
}
private RegionLocations hrll(HRegionLocation ... locations) {
return new RegionLocations(locations);
}
@Test
public void testRemoveByServer() {
RegionLocations list;
// test remove from empty list
list = new RegionLocations();
assertTrue(list == list.removeByServer(sn0));
// test remove from single element list
list = hrll(hrl(info0, sn0));
assertTrue(list == list.removeByServer(sn1));
list = list.removeByServer(sn0);
assertEquals(0, list.numNonNullElements());
// test remove from multi element list
list = hrll(hrl(info0, sn0), hrl(info1, sn1), hrl(info2, sn2), hrl(info9, sn2));
assertTrue(list == list.removeByServer(sn3)); // no region is mapped to sn3
list = list.removeByServer(sn0);
assertNull(list.getRegionLocation(0));
assertEquals(sn1, list.getRegionLocation(1).getServerName());
assertEquals(sn2, list.getRegionLocation(2).getServerName());
assertNull(list.getRegionLocation(5));
assertEquals(sn2, list.getRegionLocation(9).getServerName());
// test multi-element remove from multi element list
list = hrll(hrl(info0, sn1), hrl(info1, sn1), hrl(info2, sn0), hrl(info9, sn0));
list = list.removeByServer(sn0);
assertEquals(sn1, list.getRegionLocation(0).getServerName());
assertEquals(sn1, list.getRegionLocation(1).getServerName());
assertNull(list.getRegionLocation(2));
assertNull(list.getRegionLocation(5));
assertNull(list.getRegionLocation(9));
}
@Test
public void testRemove() {
RegionLocations list;
// test remove from empty list
list = new RegionLocations();
assertTrue(list == list.remove(hrl(info0, sn0)));
// test remove from single element list
list = hrll(hrl(info0, sn0));
assertTrue(list == list.remove(hrl(info0, sn1)));
list = list.remove(hrl(info0, sn0));
assertTrue(list.isEmpty());
// test remove from multi element list
list = hrll(hrl(info0, sn0), hrl(info1, sn1), hrl(info2, sn2), hrl(info9, sn2));
assertTrue(list == list.remove(hrl(info1, sn3))); // no region is mapped to sn3
list = list.remove(hrl(info0, sn0));
assertNull(list.getRegionLocation(0));
assertEquals(sn1, list.getRegionLocation(1).getServerName());
assertEquals(sn2, list.getRegionLocation(2).getServerName());
assertNull(list.getRegionLocation(5));
assertEquals(sn2, list.getRegionLocation(9).getServerName());
list = list.remove(hrl(info9, sn2));
assertNull(list.getRegionLocation(0));
assertEquals(sn1, list.getRegionLocation(1).getServerName());
assertEquals(sn2, list.getRegionLocation(2).getServerName());
assertNull(list.getRegionLocation(5));
assertNull(list.getRegionLocation(9));
// test multi-element remove from multi element list
list = hrll(hrl(info0, sn1), hrl(info1, sn1), hrl(info2, sn0), hrl(info9, sn0));
list = list.remove(hrl(info9, sn0));
assertEquals(sn1, list.getRegionLocation(0).getServerName());
assertEquals(sn1, list.getRegionLocation(1).getServerName());
assertEquals(sn0, list.getRegionLocation(2).getServerName());
assertNull(list.getRegionLocation(5));
assertNull(list.getRegionLocation(9));
}
@Test
public void testUpdateLocation() {
RegionLocations list;
// test add to empty list
list = new RegionLocations();
list = list.updateLocation(hrl(info0, sn1), false, false);
assertEquals(sn1, list.getRegionLocation(0).getServerName());
// test add to non-empty list
list = list.updateLocation(hrl(info9, sn3, 10), false, false);
assertEquals(sn3, list.getRegionLocation(9).getServerName());
assertEquals(10, list.size());
list = list.updateLocation(hrl(info2, sn2, 10), false, false);
assertEquals(sn2, list.getRegionLocation(2).getServerName());
assertEquals(10, list.size());
// test update greater SeqNum
list = list.updateLocation(hrl(info2, sn3, 11), false, false);
assertEquals(sn3, list.getRegionLocation(2).getServerName());
assertEquals(sn3, list.getRegionLocation(9).getServerName());
// test update equal SeqNum
list = list.updateLocation(hrl(info2, sn1, 11), false, false); // should not update
assertEquals(sn3, list.getRegionLocation(2).getServerName());
assertEquals(sn3, list.getRegionLocation(9).getServerName());
list = list.updateLocation(hrl(info2, sn1, 11), true, false); // should update
assertEquals(sn1, list.getRegionLocation(2).getServerName());
assertEquals(sn3, list.getRegionLocation(9).getServerName());
// test force update
list = list.updateLocation(hrl(info2, sn2, 9), false, true); // should update
assertEquals(sn2, list.getRegionLocation(2).getServerName());
assertEquals(sn3, list.getRegionLocation(9).getServerName());
}
@Test
public void testMergeLocations() {
RegionLocations list1, list2;
// test merge empty lists
list1 = new RegionLocations();
list2 = new RegionLocations();
assertTrue(list1 == list1.mergeLocations(list2));
// test merge non-empty and empty
list2 = hrll(hrl(info0, sn0));
list1 = list1.mergeLocations(list2);
assertEquals(sn0, list1.getRegionLocation(0).getServerName());
// test merge empty and non empty
list1 = hrll();
list1 = list2.mergeLocations(list1);
assertEquals(sn0, list1.getRegionLocation(0).getServerName());
// test merge non intersecting
list1 = hrll(hrl(info0, sn0), hrl(info1, sn1));
list2 = hrll(hrl(info2, sn2));
list1 = list2.mergeLocations(list1);
assertEquals(sn0, list1.getRegionLocation(0).getServerName());
assertEquals(sn1, list1.getRegionLocation(1).getServerName());
assertEquals(2, list1.size()); // the size is taken from the argument list to merge
// do the other way merge as well
list1 = hrll(hrl(info0, sn0), hrl(info1, sn1));
list2 = hrll(hrl(info2, sn2));
list1 = list1.mergeLocations(list2);
assertEquals(sn0, list1.getRegionLocation(0).getServerName());
assertEquals(sn1, list1.getRegionLocation(1).getServerName());
assertEquals(sn2, list1.getRegionLocation(2).getServerName());
// test intersecting lists same seqNum
list1 = hrll(hrl(info0, sn0), hrl(info1, sn1));
list2 = hrll(hrl(info0, sn2), hrl(info1, sn2), hrl(info9, sn3));
list1 = list2.mergeLocations(list1); // list1 should override
assertEquals(2, list1.size());
assertEquals(sn0, list1.getRegionLocation(0).getServerName());
assertEquals(sn1, list1.getRegionLocation(1).getServerName());
// do the other way
list1 = hrll(hrl(info0, sn0), hrl(info1, sn1));
list2 = hrll(hrl(info0, sn2), hrl(info1, sn2), hrl(info9, sn3));
list1 = list1.mergeLocations(list2); // list2 should override
assertEquals(10, list1.size());
assertEquals(sn2, list1.getRegionLocation(0).getServerName());
assertEquals(sn2, list1.getRegionLocation(1).getServerName());
assertEquals(sn3, list1.getRegionLocation(9).getServerName());
// test intersecting lists different seqNum
list1 = hrll(hrl(info0, sn0, 10), hrl(info1, sn1, 10));
list2 = hrll(hrl(info0, sn2, 11), hrl(info1, sn2, 11), hrl(info9, sn3, 11));
list1 = list1.mergeLocations(list2); // list2 should override because of seqNum
assertEquals(10, list1.size());
assertEquals(sn2, list1.getRegionLocation(0).getServerName());
assertEquals(sn2, list1.getRegionLocation(1).getServerName());
assertEquals(sn3, list1.getRegionLocation(9).getServerName());
// do the other way
list1 = hrll(hrl(info0, sn0, 10), hrl(info1, sn1, 10));
list2 = hrll(hrl(info0, sn2, 11), hrl(info1, sn2, 11), hrl(info9, sn3, 11));
list1 = list1.mergeLocations(list2); // list2 should override
assertEquals(10, list1.size());
assertEquals(sn2, list1.getRegionLocation(0).getServerName());
assertEquals(sn2, list1.getRegionLocation(1).getServerName());
assertEquals(sn3, list1.getRegionLocation(9).getServerName());
}
@Test
public void testConstructWithNullElements() {
// RegionLocations can contain null elements as well. These null elements can
RegionLocations list = new RegionLocations((HRegionLocation)null);
assertTrue(list.isEmpty());
assertEquals(1, list.size());
assertEquals(0, list.numNonNullElements());
list = new RegionLocations(null, hrl(info1, sn0));
assertFalse(list.isEmpty());
assertEquals(2, list.size());
assertEquals(1, list.numNonNullElements());
list = new RegionLocations(hrl(info0, sn0), null);
assertEquals(2, list.size());
assertEquals(1, list.numNonNullElements());
list = new RegionLocations(null, hrl(info2, sn0), null, hrl(info9, sn0));
assertEquals(10, list.size());
assertEquals(2, list.numNonNullElements());
list = new RegionLocations(null, hrl(info2, sn0), null, hrl(info9, sn0), null);
assertEquals(11, list.size());
assertEquals(2, list.numNonNullElements());
list = new RegionLocations(null, hrl(info2, sn0), null, hrl(info9, sn0), null, null);
assertEquals(12, list.size());
assertEquals(2, list.numNonNullElements());
}
}