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    // test multi-element remove from multi element list
172    list = hrll(hrl(info0, sn1), hrl(info1, sn1), hrl(info2, sn0), hrl(info9, sn0));
173    list = list.remove(hrl(info9, sn0));
174    assertEquals(sn1, list.getRegionLocation(0).getServerName());
175    assertEquals(sn1, list.getRegionLocation(1).getServerName());
176    assertEquals(sn0, list.getRegionLocation(2).getServerName());
177    assertNull(list.getRegionLocation(5));
178    assertNull(list.getRegionLocation(9));
179  }
180
181  @Test
182  public void testUpdateLocation() {
183    RegionLocations list;
184
185    // test add to empty list
186    list = new RegionLocations();
187    list = list.updateLocation(hrl(info0, sn1), false, false);
188    assertEquals(sn1, list.getRegionLocation(0).getServerName());
189
190    // test add to non-empty list
191    list = list.updateLocation(hrl(info9, sn3, 10), false, false);
192    assertEquals(sn3, list.getRegionLocation(9).getServerName());
193    assertEquals(10, list.size());
194    list = list.updateLocation(hrl(info2, sn2, 10), false, false);
195    assertEquals(sn2, list.getRegionLocation(2).getServerName());
196    assertEquals(10, list.size());
197
198    // test update greater SeqNum
199    list = list.updateLocation(hrl(info2, sn3, 11), false, false);
200    assertEquals(sn3, list.getRegionLocation(2).getServerName());
201    assertEquals(sn3, list.getRegionLocation(9).getServerName());
202
203    // test update equal SeqNum
204    list = list.updateLocation(hrl(info2, sn1, 11), false, false); // should not update
205    assertEquals(sn3, list.getRegionLocation(2).getServerName());
206    assertEquals(sn3, list.getRegionLocation(9).getServerName());
207    list = list.updateLocation(hrl(info2, sn1, 11), true, false); // should update
208    assertEquals(sn1, list.getRegionLocation(2).getServerName());
209    assertEquals(sn3, list.getRegionLocation(9).getServerName());
210
211    // test force update
212    list = list.updateLocation(hrl(info2, sn2, 9), false, true); // should update
213    assertEquals(sn2, list.getRegionLocation(2).getServerName());
214    assertEquals(sn3, list.getRegionLocation(9).getServerName());
215  }
216
217  @Test
218  public void testMergeLocations() {
219    RegionLocations list1, list2;
220
221    // test merge empty lists
222    list1 = new RegionLocations();
223    list2 = new RegionLocations();
224
225    assertTrue(list1 == list1.mergeLocations(list2));
226
227    // test merge non-empty and empty
228    list2 = hrll(hrl(info0, sn0));
229    list1 = list1.mergeLocations(list2);
230    assertEquals(sn0, list1.getRegionLocation(0).getServerName());
231
232    // test merge empty and non empty
233    list1 = hrll();
234    list1 = list2.mergeLocations(list1);
235    assertEquals(sn0, list1.getRegionLocation(0).getServerName());
236
237    // test merge non intersecting
238    list1 = hrll(hrl(info0, sn0), hrl(info1, sn1));
239    list2 = hrll(hrl(info2, sn2));
240    list1 = list2.mergeLocations(list1);
241    assertEquals(sn0, list1.getRegionLocation(0).getServerName());
242    assertEquals(sn1, list1.getRegionLocation(1).getServerName());
243    assertEquals(2, list1.size()); // the size is taken from the argument list to merge
244
245    // do the other way merge as well
246    list1 = hrll(hrl(info0, sn0), hrl(info1, sn1));
247    list2 = hrll(hrl(info2, sn2));
248    list1 = list1.mergeLocations(list2);
249    assertEquals(sn0, list1.getRegionLocation(0).getServerName());
250    assertEquals(sn1, list1.getRegionLocation(1).getServerName());
251    assertEquals(sn2, list1.getRegionLocation(2).getServerName());
252
253    // test intersecting lists same seqNum
254    list1 = hrll(hrl(info0, sn0), hrl(info1, sn1));
255    list2 = hrll(hrl(info0, sn2), hrl(info1, sn2), hrl(info9, sn3));
256    list1 = list2.mergeLocations(list1); // list1 should override
257    assertEquals(2, list1.size());
258    assertEquals(sn0, list1.getRegionLocation(0).getServerName());
259    assertEquals(sn1, list1.getRegionLocation(1).getServerName());
260
261    // do the other way
262    list1 = hrll(hrl(info0, sn0), hrl(info1, sn1));
263    list2 = hrll(hrl(info0, sn2), hrl(info1, sn2), hrl(info9, sn3));
264    list1 = list1.mergeLocations(list2); // list2 should override
265    assertEquals(10, list1.size());
266    assertEquals(sn2, list1.getRegionLocation(0).getServerName());
267    assertEquals(sn2, list1.getRegionLocation(1).getServerName());
268    assertEquals(sn3, list1.getRegionLocation(9).getServerName());
269
270    // test intersecting lists different seqNum
271    list1 = hrll(hrl(info0, sn0, 10), hrl(info1, sn1, 10));
272    list2 = hrll(hrl(info0, sn2, 11), hrl(info1, sn2, 11), hrl(info9, sn3, 11));
273    list1 = list1.mergeLocations(list2); // list2 should override because of seqNum
274    assertEquals(10, list1.size());
275    assertEquals(sn2, list1.getRegionLocation(0).getServerName());
276    assertEquals(sn2, list1.getRegionLocation(1).getServerName());
277    assertEquals(sn3, list1.getRegionLocation(9).getServerName());
278
279    // do the other way
280    list1 = hrll(hrl(info0, sn0, 10), hrl(info1, sn1, 10));
281    list2 = hrll(hrl(info0, sn2, 11), hrl(info1, sn2, 11), hrl(info9, sn3, 11));
282    list1 = list1.mergeLocations(list2); // list2 should override
283    assertEquals(10, list1.size());
284    assertEquals(sn2, list1.getRegionLocation(0).getServerName());
285    assertEquals(sn2, list1.getRegionLocation(1).getServerName());
286    assertEquals(sn3, list1.getRegionLocation(9).getServerName());
287  }
288
289  @Test
290  public void testMergeLocationsWithDifferentRegionId() {
291    RegionLocations list1, list2;
292
293    // test merging two lists. But the list2 contains region replicas with a different region id
294    HRegionInfo info0 = hri(regionId1, 0);
295    HRegionInfo info1 = hri(regionId1, 1);
296    HRegionInfo info2 = hri(regionId2, 2);
297
298    list1 = hrll(hrl(info2, sn1));
299    list2 = hrll(hrl(info0, sn2), hrl(info1, sn2));
300    list1 = list2.mergeLocations(list1);
301    assertNull(list1.getRegionLocation(0));
302    assertNull(list1.getRegionLocation(1));
303    assertNotNull(list1.getRegionLocation(2));
304    assertEquals(sn1, list1.getRegionLocation(2).getServerName());
305    assertEquals(3, list1.size());
306
307    // try the other way merge
308    list1 = hrll(hrl(info2, sn1));
309    list2 = hrll(hrl(info0, sn2), hrl(info1, sn2));
310    list2 = list1.mergeLocations(list2);
311    assertNotNull(list2.getRegionLocation(0));
312    assertNotNull(list2.getRegionLocation(1));
313    assertNull(list2.getRegionLocation(2));
314  }
315
316  @Test
317  public void testUpdateLocationWithDifferentRegionId() {
318    RegionLocations list;
319
320    HRegionInfo info0 = hri(regionId1, 0);
321    HRegionInfo info1 = hri(regionId2, 1);
322    HRegionInfo info2 = hri(regionId1, 2);
323
324    list = new RegionLocations(hrl(info0, sn1), hrl(info2, sn1));
325
326    list = list.updateLocation(hrl(info1, sn2), false, true); // force update
327
328    // the other locations should be removed now
329    assertNull(list.getRegionLocation(0));
330    assertNotNull(list.getRegionLocation(1));
331    assertNull(list.getRegionLocation(2));
332    assertEquals(sn2, list.getRegionLocation(1).getServerName());
333    assertEquals(3, list.size());
334  }
335
336  @Test
337  public void testConstructWithNullElements() {
338    // RegionLocations can contain null elements as well. These null elements can
339
340    RegionLocations list = new RegionLocations((HRegionLocation) null);
341    assertTrue(list.isEmpty());
342    assertEquals(1, list.size());
343    assertEquals(0, list.numNonNullElements());
344
345    list = new RegionLocations(null, hrl(info1, sn0));
346    assertFalse(list.isEmpty());
347    assertEquals(2, list.size());
348    assertEquals(1, list.numNonNullElements());
349
350    list = new RegionLocations(hrl(info0, sn0), null);
351    assertEquals(2, list.size());
352    assertEquals(1, list.numNonNullElements());
353
354    list = new RegionLocations(null, hrl(info2, sn0), null, hrl(info9, sn0));
355    assertEquals(10, list.size());
356    assertEquals(2, list.numNonNullElements());
357
358    list = new RegionLocations(null, hrl(info2, sn0), null, hrl(info9, sn0), null);
359    assertEquals(11, list.size());
360    assertEquals(2, list.numNonNullElements());
361
362    list = new RegionLocations(null, hrl(info2, sn0), null, hrl(info9, sn0), null, null);
363    assertEquals(12, list.size());
364    assertEquals(2, list.numNonNullElements());
365  }
366}