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.replication.regionserver;
019
020import static org.apache.hadoop.hbase.client.RegionLocator.LOCATOR_META_REPLICAS_MODE;
021import static org.junit.Assert.assertArrayEquals;
022import static org.junit.Assert.assertEquals;
023import static org.junit.Assert.assertFalse;
024import static org.junit.Assert.assertNotNull;
025import static org.junit.Assert.assertTrue;
026import java.io.IOException;
027import java.util.ArrayList;
028import java.util.Arrays;
029import java.util.List;
030import java.util.Objects;
031import org.apache.hadoop.conf.Configuration;
032import org.apache.hadoop.hbase.Cell;
033import org.apache.hadoop.hbase.CellScanner;
034import org.apache.hadoop.hbase.CellUtil;
035import org.apache.hadoop.hbase.HBaseClassTestRule;
036import org.apache.hadoop.hbase.HBaseTestingUtility;
037import org.apache.hadoop.hbase.HConstants;
038import org.apache.hadoop.hbase.HRegionLocation;
039import org.apache.hadoop.hbase.MetaTableAccessor;
040import org.apache.hadoop.hbase.MiniHBaseCluster;
041import org.apache.hadoop.hbase.TableName;
042import org.apache.hadoop.hbase.Waiter;
043import org.apache.hadoop.hbase.client.Connection;
044import org.apache.hadoop.hbase.client.ConnectionFactory;
045import org.apache.hadoop.hbase.client.Get;
046import org.apache.hadoop.hbase.client.RegionInfo;
047import org.apache.hadoop.hbase.client.RegionLocator;
048import org.apache.hadoop.hbase.client.Result;
049import org.apache.hadoop.hbase.client.Scan;
050import org.apache.hadoop.hbase.client.Table;
051import org.apache.hadoop.hbase.regionserver.HRegion;
052import org.apache.hadoop.hbase.regionserver.HRegionServer;
053import org.apache.hadoop.hbase.regionserver.Region;
054import org.apache.hadoop.hbase.regionserver.RegionScanner;
055import org.apache.hadoop.hbase.testclassification.LargeTests;
056import org.apache.hadoop.hbase.util.Bytes;
057import org.apache.hadoop.hbase.util.ServerRegionReplicaUtil;
058import org.junit.After;
059import org.junit.Before;
060import org.junit.ClassRule;
061import org.junit.Rule;
062import org.junit.Test;
063import org.junit.experimental.categories.Category;
064import org.junit.rules.TestName;
065import org.slf4j.Logger;
066import org.slf4j.LoggerFactory;
067
068/**
069 * Tests RegionReplicaReplicationEndpoint class for hbase:meta by setting up region replicas and
070 * verifying async wal replication replays the edits to the secondary region in various scenarios.
071 *
072 * @see TestRegionReplicaReplicationEndpoint
073 */
074@Category({LargeTests.class})
075public class TestMetaRegionReplicaReplicationEndpoint {
076  @ClassRule
077  public static final HBaseClassTestRule CLASS_RULE =
078    HBaseClassTestRule.forClass(TestMetaRegionReplicaReplicationEndpoint.class);
079  private static final Logger LOG =
080    LoggerFactory.getLogger(TestMetaRegionReplicaReplicationEndpoint.class);
081  private static final int NB_SERVERS = 4;
082  private final HBaseTestingUtility HTU = new HBaseTestingUtility();
083  private int numOfMetaReplica = NB_SERVERS - 1;
084  private static byte[] VALUE = Bytes.toBytes("value");
085
086  @Rule
087  public TestName name = new TestName();
088
089  @Before
090  public void before() throws Exception {
091    Configuration conf = HTU.getConfiguration();
092    conf.setFloat("hbase.regionserver.logroll.multiplier", 0.0003f);
093    conf.setInt("replication.source.size.capacity", 10240);
094    conf.setLong("replication.source.sleepforretries", 100);
095    conf.setInt("hbase.regionserver.maxlogs", 10);
096    conf.setLong("hbase.master.logcleaner.ttl", 10);
097    conf.setInt("zookeeper.recovery.retry", 1);
098    conf.setInt("zookeeper.recovery.retry.intervalmill", 10);
099    conf.setLong(HConstants.THREAD_WAKE_FREQUENCY, 100);
100    conf.setInt("replication.stats.thread.period.seconds", 5);
101    conf.setBoolean("hbase.tests.use.shortcircuit.reads", false);
102    conf.setInt(HConstants.HBASE_CLIENT_SERVERSIDE_RETRIES_MULTIPLIER, 1);
103    // Enable hbase:meta replication.
104    conf.setBoolean(ServerRegionReplicaUtil.REGION_REPLICA_REPLICATION_CATALOG_CONF_KEY,
105      true);
106    // Set hbase:meta replicas to be 3.
107    // conf.setInt(HConstants.META_REPLICAS_NUM, numOfMetaReplica);
108    HTU.startMiniCluster(NB_SERVERS);
109    // Enable hbase:meta replication.
110    HBaseTestingUtility.setReplicas(HTU.getAdmin(), TableName.META_TABLE_NAME, numOfMetaReplica);
111
112    HTU.waitFor(30000,
113      () -> HTU.getMiniHBaseCluster().getRegions(TableName.META_TABLE_NAME).size()
114      >= numOfMetaReplica);
115  }
116
117  @After
118  public void after() throws Exception {
119    HTU.shutdownMiniCluster();
120  }
121
122  /**
123   * Assert that the ReplicationSource for hbase:meta gets created when hbase:meta is opened.
124   */
125  @Test
126  public void testHBaseMetaReplicationSourceCreatedOnOpen() throws Exception {
127    MiniHBaseCluster cluster = HTU.getMiniHBaseCluster();
128    HRegionServer hrs = cluster.getRegionServer(cluster.getServerHoldingMeta());
129    // Replicate a row to prove all working.
130    testHBaseMetaReplicatesOneRow(0);
131    assertTrue(isMetaRegionReplicaReplicationSource(hrs));
132    // Now move the hbase:meta and make sure the ReplicationSource is in both places.
133    HRegionServer hrsOther = null;
134    for (int i = 0; i < cluster.getNumLiveRegionServers(); i++) {
135      hrsOther = cluster.getRegionServer(i);
136      if (hrsOther.getServerName().equals(hrs.getServerName())) {
137        hrsOther = null;
138        continue;
139      }
140      break;
141    }
142    assertNotNull(hrsOther);
143    assertFalse(isMetaRegionReplicaReplicationSource(hrsOther));
144    Region meta = null;
145    for (Region region : hrs.getOnlineRegionsLocalContext()) {
146      if (region.getRegionInfo().isMetaRegion()) {
147        meta = region;
148        break;
149      }
150    }
151    assertNotNull(meta);
152    HTU.moveRegionAndWait(meta.getRegionInfo(), hrsOther.getServerName());
153    // Assert that there is a ReplicationSource in both places now.
154    assertTrue(isMetaRegionReplicaReplicationSource(hrs));
155    assertTrue(isMetaRegionReplicaReplicationSource(hrsOther));
156    // Replicate to show stuff still works.
157    testHBaseMetaReplicatesOneRow(1);
158    // Now pretend a few hours have gone by... roll the meta WAL in original location... Move the
159    // meta back and retry replication. See if it works.
160    hrs.getWAL(meta.getRegionInfo()).rollWriter(true);
161    testHBaseMetaReplicatesOneRow(2);
162    hrs.getWAL(meta.getRegionInfo()).rollWriter(true);
163    testHBaseMetaReplicatesOneRow(3);
164  }
165
166  /**
167   * Test meta region replica replication. Create some tables and see if replicas pick up the
168   * additions.
169   */
170  private void testHBaseMetaReplicatesOneRow(int i) throws Exception {
171    waitForMetaReplicasToOnline();
172    try (Table table = HTU.createTable(TableName.valueOf(this.name.getMethodName() + "_" + i),
173      HConstants.CATALOG_FAMILY)) {
174      verifyReplication(TableName.META_TABLE_NAME, numOfMetaReplica, getMetaCells(table.getName()));
175    }
176  }
177
178  /**
179   * @return Whether the special meta region replica peer is enabled on <code>hrs</code>
180   */
181  private boolean isMetaRegionReplicaReplicationSource(HRegionServer hrs) {
182    return hrs.getReplicationSourceService().getReplicationManager().
183      catalogReplicationSource.get() != null;
184  }
185
186  /**
187   * Test meta region replica replication. Create some tables and see if replicas pick up the
188   * additions.
189   */
190  @Test
191  public void testHBaseMetaReplicates() throws Exception {
192    try (Table table = HTU
193      .createTable(TableName.valueOf(this.name.getMethodName() + "_0"), HConstants.CATALOG_FAMILY,
194        Arrays.copyOfRange(HBaseTestingUtility.KEYS, 1, HBaseTestingUtility.KEYS.length))) {
195      verifyReplication(TableName.META_TABLE_NAME, numOfMetaReplica, getMetaCells(table.getName()));
196    }
197    try (Table table = HTU
198      .createTable(TableName.valueOf(this.name.getMethodName() + "_1"), HConstants.CATALOG_FAMILY,
199        Arrays.copyOfRange(HBaseTestingUtility.KEYS, 1, HBaseTestingUtility.KEYS.length))) {
200      verifyReplication(TableName.META_TABLE_NAME, numOfMetaReplica, getMetaCells(table.getName()));
201      // Try delete.
202      HTU.deleteTableIfAny(table.getName());
203      verifyDeletedReplication(TableName.META_TABLE_NAME, numOfMetaReplica, table.getName());
204    }
205  }
206
207  @Test
208  public void testCatalogReplicaReplicationWithFlushAndCompaction() throws Exception {
209    Connection connection = ConnectionFactory.createConnection(HTU.getConfiguration());
210    TableName tableName = TableName.valueOf("hbase:meta");
211    Table table = connection.getTable(tableName);
212    try {
213      // load the data to the table
214      for (int i = 0; i < 5; i++) {
215        LOG.info("Writing data from " + i * 1000 + " to " + (i * 1000 + 1000));
216        HTU.loadNumericRows(table, HConstants.CATALOG_FAMILY, i * 1000, i * 1000 + 1000);
217        LOG.info("flushing table");
218        HTU.flush(tableName);
219        LOG.info("compacting table");
220        if (i < 4) {
221          HTU.compact(tableName, false);
222        }
223      }
224
225      verifyReplication(tableName, numOfMetaReplica, 0, 5000, HConstants.CATALOG_FAMILY);
226    } finally {
227      table.close();
228      connection.close();
229    }
230  }
231
232  @Test
233  public void testCatalogReplicaReplicationWithReplicaMoved() throws Exception {
234    MiniHBaseCluster cluster = HTU.getMiniHBaseCluster();
235    HRegionServer hrs = cluster.getRegionServer(cluster.getServerHoldingMeta());
236
237    HRegionServer hrsMetaReplica = null;
238    HRegionServer hrsNoMetaReplica = null;
239    HRegionServer server = null;
240    Region metaReplica = null;
241    boolean hostingMeta;
242
243    for (int i = 0; i < cluster.getNumLiveRegionServers(); i++) {
244      server = cluster.getRegionServer(i);
245      hostingMeta = false;
246      if (server == hrs) {
247        continue;
248      }
249      for (Region region : server.getOnlineRegionsLocalContext()) {
250        if (region.getRegionInfo().isMetaRegion()) {
251          if (metaReplica == null) {
252            metaReplica = region;
253          }
254          hostingMeta = true;
255          break;
256        }
257      }
258      if (!hostingMeta) {
259        hrsNoMetaReplica = server;
260      }
261    }
262
263    Connection connection = ConnectionFactory.createConnection(HTU.getConfiguration());
264    TableName tableName = TableName.valueOf("hbase:meta");
265    Table table = connection.getTable(tableName);
266    try {
267      // load the data to the table
268      for (int i = 0; i < 5; i++) {
269        LOG.info("Writing data from " + i * 1000 + " to " + (i * 1000 + 1000));
270        HTU.loadNumericRows(table, HConstants.CATALOG_FAMILY, i * 1000, i * 1000 + 1000);
271        if (i == 0) {
272          HTU.moveRegionAndWait(metaReplica.getRegionInfo(), hrsNoMetaReplica.getServerName());
273        }
274      }
275
276      verifyReplication(tableName, numOfMetaReplica, 0, 5000, HConstants.CATALOG_FAMILY);
277    } finally {
278      table.close();
279      connection.close();
280    }
281  }
282
283  protected void verifyReplication(TableName tableName, int regionReplication, final int startRow,
284    final int endRow, final byte[] family) throws Exception {
285    verifyReplication(tableName, regionReplication, startRow, endRow, family, true);
286  }
287
288  private void verifyReplication(TableName tableName, int regionReplication, final int startRow,
289    final int endRow, final byte[] family, final boolean present) throws Exception {
290    // find the regions
291    final Region[] regions = new Region[regionReplication];
292
293    for (int i = 0; i < NB_SERVERS; i++) {
294      HRegionServer rs = HTU.getMiniHBaseCluster().getRegionServer(i);
295      List<HRegion> onlineRegions = rs.getRegions(tableName);
296      for (HRegion region : onlineRegions) {
297        regions[region.getRegionInfo().getReplicaId()] = region;
298      }
299    }
300
301    for (Region region : regions) {
302      assertNotNull(region);
303    }
304
305    for (int i = 1; i < regionReplication; i++) {
306      final Region region = regions[i];
307      // wait until all the data is replicated to all secondary regions
308      Waiter.waitFor(HTU.getConfiguration(), 90000, 1000, new Waiter.Predicate<Exception>() {
309        @Override
310        public boolean evaluate() throws Exception {
311          LOG.info("verifying replication for region replica:" + region.getRegionInfo());
312          try {
313            HTU.verifyNumericRows(region, family, startRow, endRow, present);
314          } catch (Throwable ex) {
315            LOG.warn("Verification from secondary region is not complete yet", ex);
316            // still wait
317            return false;
318          }
319          return true;
320        }
321      });
322    }
323  }
324
325  /**
326   * Replicas come online after primary.
327   */
328  private void waitForMetaReplicasToOnline() throws IOException {
329    final RegionLocator regionLocator =
330      HTU.getConnection().getRegionLocator(TableName.META_TABLE_NAME);
331    HTU.waitFor(10000,
332      // getRegionLocations returns an entry for each replica but if unassigned, entry is null.
333      // Pass reload to force us to skip cache else it just keeps returning default.
334      () -> regionLocator.getRegionLocations(HConstants.EMPTY_START_ROW, true).stream().
335        filter(Objects::nonNull).count() >= numOfMetaReplica);
336    List<HRegionLocation> locations = regionLocator.getRegionLocations(HConstants.EMPTY_START_ROW);
337    LOG.info("Found locations {}", locations);
338    assertEquals(numOfMetaReplica, locations.size());
339  }
340
341  /**
342   * Scan hbase:meta for <code>tableName</code> content.
343   */
344  private List<Result> getMetaCells(TableName tableName) throws IOException {
345    final List<Result> results = new ArrayList<>();
346    MetaTableAccessor.Visitor visitor = new MetaTableAccessor.Visitor() {
347      @Override public boolean visit(Result r) throws IOException {
348        results.add(r);
349        return true;
350      }
351    };
352    MetaTableAccessor.scanMetaForTableRegions(HTU.getConnection(), visitor, tableName);
353    return results;
354  }
355
356  /**
357   * @return All Regions for tableName including Replicas.
358   */
359  private Region[] getAllRegions(TableName tableName, int replication) {
360    final Region[] regions = new Region[replication];
361    for (int i = 0; i < NB_SERVERS; i++) {
362      HRegionServer rs = HTU.getMiniHBaseCluster().getRegionServer(i);
363      List<HRegion> onlineRegions = rs.getRegions(tableName);
364      for (HRegion region : onlineRegions) {
365        regions[region.getRegionInfo().getReplicaId()] = region;
366      }
367    }
368    for (Region region : regions) {
369      assertNotNull(region);
370    }
371    return regions;
372  }
373
374  private Region getOneRegion(TableName tableName) {
375    for (int i = 0; i < NB_SERVERS; i++) {
376      HRegionServer rs = HTU.getMiniHBaseCluster().getRegionServer(i);
377      List<HRegion> onlineRegions = rs.getRegions(tableName);
378      if (onlineRegions.size() > 1) {
379        return onlineRegions.get(0);
380      }
381    }
382    return null;
383  }
384
385  /**
386   * Verify when a Table is deleted from primary, then there are no references in replicas
387   * (because they get the delete of the table rows too).
388   */
389  private void verifyDeletedReplication(TableName tableName, int regionReplication,
390    final TableName deletedTableName) {
391    final Region[] regions = getAllRegions(tableName, regionReplication);
392
393    // Start count at '1' so we skip default, primary replica and only look at secondaries.
394    for (int i = 1; i < regionReplication; i++) {
395      final Region region = regions[i];
396      // wait until all the data is replicated to all secondary regions
397      Waiter.waitFor(HTU.getConfiguration(), 30000, 1000, new Waiter.Predicate<Exception>() {
398        @Override
399        public boolean evaluate() throws Exception {
400          LOG.info("Verifying replication for region replica {}", region.getRegionInfo());
401          try (RegionScanner rs = region.getScanner(new Scan())) {
402            List<Cell> cells = new ArrayList<>();
403            while (rs.next(cells)) {
404              continue;
405            }
406            return doesNotContain(cells, deletedTableName);
407          } catch (Throwable ex) {
408            LOG.warn("Verification from secondary region is not complete yet", ex);
409            // still wait
410            return false;
411          }
412        }
413      });
414    }
415  }
416
417  /**
418   * Cells are from hbase:meta replica so will start w/ 'tableName,'; i.e. the tablename followed
419   * by HConstants.DELIMITER. Make sure the deleted table is no longer present in passed
420   * <code>cells</code>.
421   */
422  private boolean doesNotContain(List<Cell> cells, TableName tableName) {
423    for (Cell cell : cells) {
424      String row = Bytes.toString(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
425      if (row.startsWith(tableName.toString() + HConstants.DELIMITER)) {
426        return false;
427      }
428    }
429    return true;
430  }
431
432  /**
433   * Verify Replicas have results (exactly).
434   */
435  private void verifyReplication(TableName tableName, int regionReplication,
436    List<Result> contains) {
437    final Region[] regions = getAllRegions(tableName, regionReplication);
438
439    // Start count at '1' so we skip default, primary replica and only look at secondaries.
440    for (int i = 1; i < regionReplication; i++) {
441      final Region region = regions[i];
442      // wait until all the data is replicated to all secondary regions
443      Waiter.waitFor(HTU.getConfiguration(), 30000, 1000, new Waiter.Predicate<Exception>() {
444        @Override
445        public boolean evaluate() throws Exception {
446          LOG.info("Verifying replication for region replica {}", region.getRegionInfo());
447          try (RegionScanner rs = region.getScanner(new Scan())) {
448            List<Cell> cells = new ArrayList<>();
449            while (rs.next(cells)) {
450              continue;
451            }
452            return contains(contains, cells);
453          } catch (Throwable ex) {
454            LOG.warn("Verification from secondary region is not complete yet", ex);
455            // still wait
456            return false;
457          }
458        }
459      });
460    }
461  }
462
463  /**
464   * Presumes sorted Cells. Verify that <code>cells</code> has <code>contains</code> at least.
465   */
466  static boolean contains(List<Result> contains, List<Cell> cells) throws IOException {
467    CellScanner containsScanner = CellUtil.createCellScanner(contains);
468    CellScanner cellsScanner = CellUtil.createCellScanner(cells);
469    int matches = 0;
470    int count = 0;
471    while (containsScanner.advance()) {
472      while (cellsScanner.advance()) {
473        count++;
474        LOG.info("{} {}", containsScanner.current(), cellsScanner.current());
475        if (containsScanner.current().equals(cellsScanner.current())) {
476          matches++;
477          break;
478        }
479      }
480    }
481    return !containsScanner.advance() && matches >= 1 && count >= matches && count == cells.size();
482  }
483
484  private void doNGets(final Table table, final byte[][] keys) throws Exception {
485    for (byte[] key : keys) {
486      Result r = table.get(new Get(key));
487      assertArrayEquals(VALUE, r.getValue(HConstants.CATALOG_FAMILY, HConstants.CATALOG_FAMILY));
488    }
489  }
490
491  private void primaryNoChangeReplicaIncrease(final long[] before, final long[] after) {
492    assertEquals(before[RegionInfo.DEFAULT_REPLICA_ID],
493      after[RegionInfo.DEFAULT_REPLICA_ID]);
494
495    for (int i = 1; i < after.length; i ++) {
496      assertTrue(after[i] > before[i]);
497    }
498  }
499
500  private void primaryIncreaseReplicaNoChange(final long[] before, final long[] after) {
501    // There are read requests increase for primary meta replica.
502    assertTrue(after[RegionInfo.DEFAULT_REPLICA_ID] >
503      before[RegionInfo.DEFAULT_REPLICA_ID]);
504
505    // No change for replica regions
506    for (int i = 1; i < after.length; i ++) {
507      assertEquals(before[i], after[i]);
508    }
509  }
510
511  private void primaryMayIncreaseReplicaNoChange(final long[] before, final long[] after) {
512    // For primary meta replica, scan request may increase. No change for replica meta regions.
513    assertTrue(after[RegionInfo.DEFAULT_REPLICA_ID] >=
514      before[RegionInfo.DEFAULT_REPLICA_ID]);
515
516    // No change for replica regions
517    for (int i = 1; i < after.length; i ++) {
518      assertEquals(before[i], after[i]);
519    }
520  }
521
522  private void getMetaReplicaReadRequests(final Region[] metaRegions, final long[] counters) {
523    int i = 0;
524    for (Region r : metaRegions) {
525      LOG.info("read request for region {} is {}", r, r.getReadRequestsCount());
526      counters[i] = r.getReadRequestsCount();
527      i ++;
528    }
529  }
530
531  @Test
532  public void testHBaseMetaReplicaGets() throws Exception {
533
534    TableName tn = TableName.valueOf(this.name.getMethodName());
535    final Region[] metaRegions = getAllRegions(TableName.META_TABLE_NAME, numOfMetaReplica);
536    long[] readReqsForMetaReplicas = new long[numOfMetaReplica];
537    long[] readReqsForMetaReplicasAfterGet = new long[numOfMetaReplica];
538    long[] readReqsForMetaReplicasAfterMove = new long[numOfMetaReplica];
539    long[] readReqsForMetaReplicasAfterSecondMove = new long[numOfMetaReplica];
540    long[] readReqsForMetaReplicasAfterThirdGet = new long[numOfMetaReplica];
541    Region userRegion = null;
542    HRegionServer srcRs = null;
543    HRegionServer destRs = null;
544
545    try (Table table = HTU.createTable(tn, HConstants.CATALOG_FAMILY,
546      Arrays.copyOfRange(HBaseTestingUtility.KEYS, 1, HBaseTestingUtility.KEYS.length))) {
547      verifyReplication(TableName.META_TABLE_NAME, numOfMetaReplica, getMetaCells(table.getName()));
548      // load different values
549      HTU.loadTable(table, new byte[][] { HConstants.CATALOG_FAMILY }, VALUE);
550      for (int i = 0; i < NB_SERVERS; i++) {
551        HRegionServer rs = HTU.getMiniHBaseCluster().getRegionServer(i);
552        List<HRegion> onlineRegions = rs.getRegions(tn);
553        if (onlineRegions.size() > 0) {
554          userRegion = onlineRegions.get(0);
555          srcRs = rs;
556          if (i > 0) {
557            destRs = HTU.getMiniHBaseCluster().getRegionServer(0);
558          } else {
559            destRs = HTU.getMiniHBaseCluster().getRegionServer(1);
560          }
561        }
562      }
563
564      getMetaReplicaReadRequests(metaRegions, readReqsForMetaReplicas);
565
566      Configuration c = new Configuration(HTU.getConfiguration());
567      c.set(LOCATOR_META_REPLICAS_MODE, "LoadBalance");
568      Connection connection = ConnectionFactory.createConnection(c);
569      Table tableForGet = connection.getTable(tn);
570      byte[][] getRows = new byte[HBaseTestingUtility.KEYS.length][];
571
572      int i = 0;
573      for (byte[] key : HBaseTestingUtility.KEYS) {
574        getRows[i] = key;
575        i++;
576      }
577      getRows[0] = Bytes.toBytes("aaa");
578      doNGets(tableForGet, getRows);
579
580      getMetaReplicaReadRequests(metaRegions, readReqsForMetaReplicasAfterGet);
581
582      // There is no read requests increase for primary meta replica.
583      // For rest of meta replicas, there are more reads against them.
584      primaryNoChangeReplicaIncrease(readReqsForMetaReplicas, readReqsForMetaReplicasAfterGet);
585
586      // move one of regions so it meta cache may be invalid.
587      HTU.moveRegionAndWait(userRegion.getRegionInfo(), destRs.getServerName());
588
589      doNGets(tableForGet, getRows);
590
591      getMetaReplicaReadRequests(metaRegions, readReqsForMetaReplicasAfterMove);
592
593      // There are read requests increase for primary meta replica.
594      // For rest of meta replicas, there is no change as regionMove will tell the new location
595      primaryIncreaseReplicaNoChange(readReqsForMetaReplicasAfterGet,
596        readReqsForMetaReplicasAfterMove);
597      // Move region again.
598      HTU.moveRegionAndWait(userRegion.getRegionInfo(), srcRs.getServerName());
599
600      // Wait until moveRegion cache timeout.
601      while (destRs.getMovedRegion(userRegion.getRegionInfo().getEncodedName()) != null) {
602        Thread.sleep(1000);
603      }
604
605      getMetaReplicaReadRequests(metaRegions, readReqsForMetaReplicasAfterSecondMove);
606
607      // There may be read requests increase for primary meta replica.
608      // For rest of meta replicas, there is no change.
609      primaryMayIncreaseReplicaNoChange(readReqsForMetaReplicasAfterMove,
610        readReqsForMetaReplicasAfterSecondMove);
611
612      doNGets(tableForGet, getRows);
613
614      getMetaReplicaReadRequests(metaRegions, readReqsForMetaReplicasAfterThirdGet);
615
616      // Since it gets RegionNotServedException, it will go to primary for the next lookup.
617      // There are read requests increase for primary meta replica.
618      // For rest of meta replicas, there is no change.
619      primaryIncreaseReplicaNoChange(readReqsForMetaReplicasAfterSecondMove,
620        readReqsForMetaReplicasAfterThirdGet);
621    }
622  }
623}