001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertFalse;
022import static org.junit.Assert.assertNotNull;
023import static org.junit.Assert.assertNull;
024import static org.junit.Assert.assertTrue;
025
026import org.apache.hadoop.hbase.testclassification.ClientTests;
027import org.apache.hadoop.hbase.testclassification.SmallTests;
028import org.junit.ClassRule;
029import org.junit.Test;
030import org.junit.experimental.categories.Category;
031
032@Category({ClientTests.class, SmallTests.class})
033public class TestRegionLocations {
034
035  @ClassRule
036  public static final HBaseClassTestRule CLASS_RULE =
037      HBaseClassTestRule.forClass(TestRegionLocations.class);
038
039  ServerName sn0 = ServerName.valueOf("host0", 10, 10);
040  ServerName sn1 = ServerName.valueOf("host1", 10, 10);
041  ServerName sn2 = ServerName.valueOf("host2", 10, 10);
042  ServerName sn3 = ServerName.valueOf("host3", 10, 10);
043
044  HRegionInfo info0 = hri(0);
045  HRegionInfo info1 = hri(1);
046  HRegionInfo info2 = hri(2);
047  HRegionInfo info9 = hri(9);
048
049  long regionId1 = 1000;
050  long regionId2 = 2000;
051
052  @Test
053  public void testSizeMethods() {
054    RegionLocations list = new RegionLocations();
055    assertTrue(list.isEmpty());
056    assertEquals(0, list.size());
057    assertEquals(0, list.numNonNullElements());
058
059    list = hrll((HRegionLocation)null);
060    assertTrue(list.isEmpty());
061    assertEquals(1, list.size());
062    assertEquals(0, list.numNonNullElements());
063
064    HRegionInfo info0 = hri(0);
065    list = hrll(hrl(info0, null));
066    assertTrue(list.isEmpty());
067    assertEquals(1, list.size());
068    assertEquals(0, list.numNonNullElements());
069
070    HRegionInfo info9 = hri(9);
071    list = hrll(hrl(info9, null));
072    assertTrue(list.isEmpty());
073    assertEquals(10, list.size());
074    assertEquals(0, list.numNonNullElements());
075
076    list = hrll(hrl(info0, null), hrl(info9, null));
077    assertTrue(list.isEmpty());
078    assertEquals(10, list.size());
079    assertEquals(0, list.numNonNullElements());
080  }
081
082  private HRegionInfo hri(int replicaId) {
083    return hri(regionId1, replicaId);
084  }
085
086  private HRegionInfo hri(long regionId, int replicaId) {
087    TableName table = TableName.valueOf("table");
088    byte[] startKey = HConstants.EMPTY_START_ROW;
089    byte[] endKey = HConstants.EMPTY_END_ROW;
090    HRegionInfo info = new HRegionInfo(table, startKey, endKey, false, regionId, replicaId);
091    return info;
092  }
093
094  private HRegionLocation hrl(HRegionInfo hri, ServerName sn) {
095    return new HRegionLocation(hri, sn);
096  }
097
098  private HRegionLocation hrl(HRegionInfo hri, ServerName sn, long seqNum) {
099    return new HRegionLocation(hri, sn, seqNum);
100  }
101
102  private RegionLocations hrll(HRegionLocation ... locations) {
103    return new RegionLocations(locations);
104  }
105
106  @Test
107  public void testRemoveByServer() {
108    RegionLocations list;
109
110    // test remove from empty list
111    list = new RegionLocations();
112    assertTrue(list == list.removeByServer(sn0));
113
114    // test remove from single element list
115    list = hrll(hrl(info0, sn0));
116    assertTrue(list == list.removeByServer(sn1));
117    list = list.removeByServer(sn0);
118    assertEquals(0, list.numNonNullElements());
119
120    // test remove from multi element list
121    list = hrll(hrl(info0, sn0), hrl(info1, sn1), hrl(info2, sn2), hrl(info9, sn2));
122    assertTrue(list == list.removeByServer(sn3)); // no region is mapped to sn3
123    list = list.removeByServer(sn0);
124    assertNull(list.getRegionLocation(0));
125    assertEquals(sn1, list.getRegionLocation(1).getServerName());
126    assertEquals(sn2, list.getRegionLocation(2).getServerName());
127    assertNull(list.getRegionLocation(5));
128    assertEquals(sn2, list.getRegionLocation(9).getServerName());
129
130    // test multi-element remove from multi element list
131    list = hrll(hrl(info0, sn1), hrl(info1, sn1), hrl(info2, sn0), hrl(info9, sn0));
132    list = list.removeByServer(sn0);
133    assertEquals(sn1, list.getRegionLocation(0).getServerName());
134    assertEquals(sn1, list.getRegionLocation(1).getServerName());
135    assertNull(list.getRegionLocation(2));
136    assertNull(list.getRegionLocation(5));
137    assertNull(list.getRegionLocation(9));
138  }
139
140  @Test
141  public void testRemove() {
142    RegionLocations list;
143
144    // test remove from empty list
145    list = new RegionLocations();
146    assertTrue(list == list.remove(hrl(info0, sn0)));
147
148    // test remove from single element list
149    list = hrll(hrl(info0, sn0));
150    assertTrue(list == list.remove(hrl(info0, sn1)));
151    list = list.remove(hrl(info0, sn0));
152    assertTrue(list.isEmpty());
153
154    // test remove from multi element list
155    list = hrll(hrl(info0, sn0), hrl(info1, sn1), hrl(info2, sn2), hrl(info9, sn2));
156    assertTrue(list == list.remove(hrl(info1, sn3))); // no region is mapped to sn3
157    list = list.remove(hrl(info0, sn0));
158    assertNull(list.getRegionLocation(0));
159    assertEquals(sn1, list.getRegionLocation(1).getServerName());
160    assertEquals(sn2, list.getRegionLocation(2).getServerName());
161    assertNull(list.getRegionLocation(5));
162    assertEquals(sn2, list.getRegionLocation(9).getServerName());
163
164    list = list.remove(hrl(info9, sn2));
165    assertNull(list.getRegionLocation(0));
166    assertEquals(sn1, list.getRegionLocation(1).getServerName());
167    assertEquals(sn2, list.getRegionLocation(2).getServerName());
168    assertNull(list.getRegionLocation(5));
169    assertNull(list.getRegionLocation(9));
170
171
172    // test multi-element remove from multi element list
173    list = hrll(hrl(info0, sn1), hrl(info1, sn1), hrl(info2, sn0), hrl(info9, sn0));
174    list = list.remove(hrl(info9, sn0));
175    assertEquals(sn1, list.getRegionLocation(0).getServerName());
176    assertEquals(sn1, list.getRegionLocation(1).getServerName());
177    assertEquals(sn0, list.getRegionLocation(2).getServerName());
178    assertNull(list.getRegionLocation(5));
179    assertNull(list.getRegionLocation(9));
180  }
181
182  @Test
183  public void testUpdateLocation() {
184    RegionLocations list;
185
186    // test add to empty list
187    list = new RegionLocations();
188    list = list.updateLocation(hrl(info0, sn1), false, false);
189    assertEquals(sn1, list.getRegionLocation(0).getServerName());
190
191    // test add to non-empty list
192    list = list.updateLocation(hrl(info9, sn3, 10), false, false);
193    assertEquals(sn3, list.getRegionLocation(9).getServerName());
194    assertEquals(10, list.size());
195    list = list.updateLocation(hrl(info2, sn2, 10), false, false);
196    assertEquals(sn2, list.getRegionLocation(2).getServerName());
197    assertEquals(10, list.size());
198
199    // test update greater SeqNum
200    list = list.updateLocation(hrl(info2, sn3, 11), false, false);
201    assertEquals(sn3, list.getRegionLocation(2).getServerName());
202    assertEquals(sn3, list.getRegionLocation(9).getServerName());
203
204    // test update equal SeqNum
205    list = list.updateLocation(hrl(info2, sn1, 11), false, false); // should not update
206    assertEquals(sn3, list.getRegionLocation(2).getServerName());
207    assertEquals(sn3, list.getRegionLocation(9).getServerName());
208    list = list.updateLocation(hrl(info2, sn1, 11), true, false); // should update
209    assertEquals(sn1, list.getRegionLocation(2).getServerName());
210    assertEquals(sn3, list.getRegionLocation(9).getServerName());
211
212    // test force update
213    list = list.updateLocation(hrl(info2, sn2, 9), false, true); // should update
214    assertEquals(sn2, list.getRegionLocation(2).getServerName());
215    assertEquals(sn3, list.getRegionLocation(9).getServerName());
216  }
217
218  @Test
219  public void testMergeLocations() {
220    RegionLocations list1, list2;
221
222    // test merge empty lists
223    list1 = new RegionLocations();
224    list2 = new RegionLocations();
225
226    assertTrue(list1 == list1.mergeLocations(list2));
227
228    // test merge non-empty and empty
229    list2 = hrll(hrl(info0, sn0));
230    list1 = list1.mergeLocations(list2);
231    assertEquals(sn0, list1.getRegionLocation(0).getServerName());
232
233    // test merge empty and non empty
234    list1 = hrll();
235    list1 = list2.mergeLocations(list1);
236    assertEquals(sn0, list1.getRegionLocation(0).getServerName());
237
238    // test merge non intersecting
239    list1 = hrll(hrl(info0, sn0), hrl(info1, sn1));
240    list2 = hrll(hrl(info2, sn2));
241    list1 = list2.mergeLocations(list1);
242    assertEquals(sn0, list1.getRegionLocation(0).getServerName());
243    assertEquals(sn1, list1.getRegionLocation(1).getServerName());
244    assertEquals(2, list1.size()); // the size is taken from the argument list to merge
245
246    // do the other way merge as well
247    list1 = hrll(hrl(info0, sn0), hrl(info1, sn1));
248    list2 = hrll(hrl(info2, sn2));
249    list1 = list1.mergeLocations(list2);
250    assertEquals(sn0, list1.getRegionLocation(0).getServerName());
251    assertEquals(sn1, list1.getRegionLocation(1).getServerName());
252    assertEquals(sn2, list1.getRegionLocation(2).getServerName());
253
254    // test intersecting lists same seqNum
255    list1 = hrll(hrl(info0, sn0), hrl(info1, sn1));
256    list2 = hrll(hrl(info0, sn2), hrl(info1, sn2), hrl(info9, sn3));
257    list1 = list2.mergeLocations(list1); // list1 should override
258    assertEquals(2, list1.size());
259    assertEquals(sn0, list1.getRegionLocation(0).getServerName());
260    assertEquals(sn1, list1.getRegionLocation(1).getServerName());
261
262    // do the other way
263    list1 = hrll(hrl(info0, sn0), hrl(info1, sn1));
264    list2 = hrll(hrl(info0, sn2), hrl(info1, sn2), hrl(info9, sn3));
265    list1 = list1.mergeLocations(list2); // list2 should override
266    assertEquals(10, list1.size());
267    assertEquals(sn2, list1.getRegionLocation(0).getServerName());
268    assertEquals(sn2, list1.getRegionLocation(1).getServerName());
269    assertEquals(sn3, list1.getRegionLocation(9).getServerName());
270
271    // test intersecting lists different seqNum
272    list1 = hrll(hrl(info0, sn0, 10), hrl(info1, sn1, 10));
273    list2 = hrll(hrl(info0, sn2, 11), hrl(info1, sn2, 11), hrl(info9, sn3, 11));
274    list1 = list1.mergeLocations(list2); // list2 should override because of seqNum
275    assertEquals(10, list1.size());
276    assertEquals(sn2, list1.getRegionLocation(0).getServerName());
277    assertEquals(sn2, list1.getRegionLocation(1).getServerName());
278    assertEquals(sn3, list1.getRegionLocation(9).getServerName());
279
280    // do the other way
281    list1 = hrll(hrl(info0, sn0, 10), hrl(info1, sn1, 10));
282    list2 = hrll(hrl(info0, sn2, 11), hrl(info1, sn2, 11), hrl(info9, sn3, 11));
283    list1 = list1.mergeLocations(list2); // list2 should override
284    assertEquals(10, list1.size());
285    assertEquals(sn2, list1.getRegionLocation(0).getServerName());
286    assertEquals(sn2, list1.getRegionLocation(1).getServerName());
287    assertEquals(sn3, list1.getRegionLocation(9).getServerName());
288  }
289
290  @Test
291  public void testMergeLocationsWithDifferentRegionId() {
292    RegionLocations list1, list2;
293
294    // test merging two lists. But the list2 contains region replicas with a different region id
295    HRegionInfo info0 = hri(regionId1, 0);
296    HRegionInfo info1 = hri(regionId1, 1);
297    HRegionInfo info2 = hri(regionId2, 2);
298
299    list1 = hrll(hrl(info2, sn1));
300    list2 = hrll(hrl(info0, sn2), hrl(info1, sn2));
301    list1 = list2.mergeLocations(list1);
302    assertNull(list1.getRegionLocation(0));
303    assertNull(list1.getRegionLocation(1));
304    assertNotNull(list1.getRegionLocation(2));
305    assertEquals(sn1, list1.getRegionLocation(2).getServerName());
306    assertEquals(3, list1.size());
307
308    // try the other way merge
309    list1 = hrll(hrl(info2, sn1));
310    list2 = hrll(hrl(info0, sn2), hrl(info1, sn2));
311    list2 = list1.mergeLocations(list2);
312    assertNotNull(list2.getRegionLocation(0));
313    assertNotNull(list2.getRegionLocation(1));
314    assertNull(list2.getRegionLocation(2));
315  }
316
317  @Test
318  public void testUpdateLocationWithDifferentRegionId() {
319    RegionLocations list;
320
321    HRegionInfo info0 = hri(regionId1, 0);
322    HRegionInfo info1 = hri(regionId2, 1);
323    HRegionInfo info2 = hri(regionId1, 2);
324
325    list = new RegionLocations(hrl(info0, sn1), hrl(info2, sn1));
326
327    list = list.updateLocation(hrl(info1, sn2), false, true); // force update
328
329    // the other locations should be removed now
330    assertNull(list.getRegionLocation(0));
331    assertNotNull(list.getRegionLocation(1));
332    assertNull(list.getRegionLocation(2));
333    assertEquals(sn2, list.getRegionLocation(1).getServerName());
334    assertEquals(3, list.size());
335  }
336
337
338  @Test
339  public void testConstructWithNullElements() {
340    // RegionLocations can contain null elements as well. These null elements can
341
342    RegionLocations list = new RegionLocations((HRegionLocation)null);
343    assertTrue(list.isEmpty());
344    assertEquals(1, list.size());
345    assertEquals(0, list.numNonNullElements());
346
347    list = new RegionLocations(null, hrl(info1, sn0));
348    assertFalse(list.isEmpty());
349    assertEquals(2, list.size());
350    assertEquals(1, list.numNonNullElements());
351
352    list = new RegionLocations(hrl(info0, sn0), null);
353    assertEquals(2, list.size());
354    assertEquals(1, list.numNonNullElements());
355
356    list = new RegionLocations(null, hrl(info2, sn0), null, hrl(info9, sn0));
357    assertEquals(10, list.size());
358    assertEquals(2, list.numNonNullElements());
359
360    list = new RegionLocations(null, hrl(info2, sn0), null, hrl(info9, sn0), null);
361    assertEquals(11, list.size());
362    assertEquals(2, list.numNonNullElements());
363
364    list = new RegionLocations(null, hrl(info2, sn0), null, hrl(info9, sn0), null, null);
365    assertEquals(12, list.size());
366    assertEquals(2, list.numNonNullElements());
367  }
368}