View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertFalse;
23  import static org.junit.Assert.assertNotNull;
24  import static org.junit.Assert.assertNull;
25  import static org.junit.Assert.assertTrue;
26  
27  import java.io.IOException;
28  import java.util.List;
29  import java.util.Random;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.hadoop.conf.Configuration;
34  import org.apache.hadoop.hbase.client.Admin;
35  import org.apache.hadoop.hbase.client.Connection;
36  import org.apache.hadoop.hbase.client.ConnectionFactory;
37  import org.apache.hadoop.hbase.client.Get;
38  import org.apache.hadoop.hbase.client.HTable;
39  import org.apache.hadoop.hbase.client.RegionLocator;
40  import org.apache.hadoop.hbase.client.Result;
41  import org.apache.hadoop.hbase.client.Table;
42  import org.apache.hadoop.hbase.testclassification.MediumTests;
43  import org.apache.hadoop.hbase.util.Bytes;
44  import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
45  import org.apache.hadoop.hbase.util.Pair;
46  import org.junit.AfterClass;
47  import org.junit.Assert;
48  import org.junit.BeforeClass;
49  import org.junit.Test;
50  import org.junit.experimental.categories.Category;
51  
52  import com.google.common.collect.Lists;
53  
54  /**
55   * Test {@link org.apache.hadoop.hbase.MetaTableAccessor}.
56   */
57  @Category(MediumTests.class)
58  public class TestMetaTableAccessor {
59    private static final Log LOG = LogFactory.getLog(TestMetaTableAccessor.class);
60    private static final  HBaseTestingUtility UTIL = new HBaseTestingUtility();
61    private static Connection connection;
62    private Random random = new Random();
63  
64    @BeforeClass public static void beforeClass() throws Exception {
65      UTIL.startMiniCluster(3);
66  
67      Configuration c = new Configuration(UTIL.getConfiguration());
68      // Tests to 4 retries every 5 seconds. Make it try every 1 second so more
69      // responsive.  1 second is default as is ten retries.
70      c.setLong("hbase.client.pause", 1000);
71      c.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 10);
72      connection = ConnectionFactory.createConnection(c);
73    }
74  
75    @AfterClass public static void afterClass() throws Exception {
76      connection.close();
77      UTIL.shutdownMiniCluster();
78    }
79  
80    /**
81     * Does {@link MetaTableAccessor#getRegion(Connection, byte[])} and a write
82     * against hbase:meta while its hosted server is restarted to prove our retrying
83     * works.
84     * @throws IOException
85     * @throws InterruptedException
86     */
87    @Test public void testRetrying()
88    throws IOException, InterruptedException {
89      final TableName name =
90          TableName.valueOf("testRetrying");
91      LOG.info("Started " + name);
92      HTable t = UTIL.createMultiRegionTable(name, HConstants.CATALOG_FAMILY);
93      int regionCount = -1;
94      try (RegionLocator r = t.getRegionLocator()) {
95        regionCount = r.getStartKeys().length;
96      }
97      // Test it works getting a region from just made user table.
98      final List<HRegionInfo> regions =
99        testGettingTableRegions(connection, name, regionCount);
100     MetaTask reader = new MetaTask(connection, "reader") {
101       @Override
102       void metaTask() throws Throwable {
103         testGetRegion(connection, regions.get(0));
104         LOG.info("Read " + regions.get(0).getEncodedName());
105       }
106     };
107     MetaTask writer = new MetaTask(connection, "writer") {
108       @Override
109       void metaTask() throws Throwable {
110         MetaTableAccessor.addRegionToMeta(connection, regions.get(0));
111         LOG.info("Wrote " + regions.get(0).getEncodedName());
112       }
113     };
114     reader.start();
115     writer.start();
116 
117     // We're gonna check how it takes. If it takes too long, we will consider
118     //  it as a fail. We can't put that in the @Test tag as we want to close
119     //  the threads nicely
120     final long timeOut = 180000;
121     long startTime = System.currentTimeMillis();
122 
123     try {
124       // Make sure reader and writer are working.
125       assertTrue(reader.isProgressing());
126       assertTrue(writer.isProgressing());
127 
128       // Kill server hosting meta -- twice  . See if our reader/writer ride over the
129       // meta moves.  They'll need to retry.
130       for (int i = 0; i < 2; i++) {
131         LOG.info("Restart=" + i);
132         UTIL.ensureSomeRegionServersAvailable(2);
133         int index = -1;
134         do {
135           index = UTIL.getMiniHBaseCluster().getServerWithMeta();
136         } while (index == -1 &&
137           startTime + timeOut < System.currentTimeMillis());
138 
139         if (index != -1){
140           UTIL.getMiniHBaseCluster().abortRegionServer(index);
141           UTIL.getMiniHBaseCluster().waitOnRegionServer(index);
142         }
143       }
144 
145       assertTrue("reader: " + reader.toString(), reader.isProgressing());
146       assertTrue("writer: " + writer.toString(), writer.isProgressing());
147     } catch (IOException e) {
148       throw e;
149     } finally {
150       reader.stop = true;
151       writer.stop = true;
152       reader.join();
153       writer.join();
154       t.close();
155     }
156     long exeTime = System.currentTimeMillis() - startTime;
157     assertTrue("Timeout: test took " + exeTime / 1000 + " sec", exeTime < timeOut);
158   }
159 
160   /**
161    * Thread that runs a MetaTableAccessor task until asked stop.
162    */
163   abstract static class MetaTask extends Thread {
164     boolean stop = false;
165     int count = 0;
166     Throwable t = null;
167     final Connection connection;
168 
169     MetaTask(final Connection connection, final String name) {
170       super(name);
171       this.connection = connection;
172     }
173 
174     @Override
175     public void run() {
176       try {
177         while(!this.stop) {
178           LOG.info("Before " + this.getName()+ ", count=" + this.count);
179           metaTask();
180           this.count += 1;
181           LOG.info("After " + this.getName() + ", count=" + this.count);
182           Thread.sleep(100);
183         }
184       } catch (Throwable t) {
185         LOG.info(this.getName() + " failed", t);
186         this.t = t;
187       }
188     }
189 
190     boolean isProgressing() throws InterruptedException {
191       int currentCount = this.count;
192       while(currentCount == this.count) {
193         if (!isAlive()) return false;
194         if (this.t != null) return false;
195         Thread.sleep(10);
196       }
197       return true;
198     }
199 
200     @Override
201     public String toString() {
202       return "count=" + this.count + ", t=" +
203         (this.t == null? "null": this.t.toString());
204     }
205 
206     abstract void metaTask() throws Throwable;
207   }
208 
209   @Test public void testGetRegionsCatalogTables()
210   throws IOException, InterruptedException {
211     List<HRegionInfo> regions =
212       MetaTableAccessor.getTableRegions(UTIL.getZooKeeperWatcher(),
213         connection, TableName.META_TABLE_NAME);
214     assertTrue(regions.size() >= 1);
215     assertTrue(MetaTableAccessor.getTableRegionsAndLocations(UTIL.getZooKeeperWatcher(),
216       connection,TableName.META_TABLE_NAME).size() >= 1);
217   }
218 
219   @Test public void testTableExists() throws IOException {
220     final TableName name =
221         TableName.valueOf("testTableExists");
222     assertFalse(MetaTableAccessor.tableExists(connection, name));
223     UTIL.createTable(name, HConstants.CATALOG_FAMILY);
224     assertTrue(MetaTableAccessor.tableExists(connection, name));
225     Admin admin = UTIL.getHBaseAdmin();
226     admin.disableTable(name);
227     admin.deleteTable(name);
228     assertFalse(MetaTableAccessor.tableExists(connection, name));
229     assertTrue(MetaTableAccessor.tableExists(connection,
230       TableName.META_TABLE_NAME));
231   }
232 
233   @Test public void testGetRegion() throws IOException, InterruptedException {
234     final String name = "testGetRegion";
235     LOG.info("Started " + name);
236     // Test get on non-existent region.
237     Pair<HRegionInfo, ServerName> pair =
238       MetaTableAccessor.getRegion(connection, Bytes.toBytes("nonexistent-region"));
239     assertNull(pair);
240     LOG.info("Finished " + name);
241   }
242 
243   // Test for the optimization made in HBASE-3650
244   @Test public void testScanMetaForTable()
245   throws IOException, InterruptedException {
246     final TableName name =
247         TableName.valueOf("testScanMetaForTable");
248     LOG.info("Started " + name);
249 
250     /** Create 2 tables
251      - testScanMetaForTable
252      - testScanMetaForTablf
253     **/
254 
255     UTIL.createTable(name, HConstants.CATALOG_FAMILY);
256     // name that is +1 greater than the first one (e+1=f)
257     TableName greaterName =
258         TableName.valueOf("testScanMetaForTablf");
259     UTIL.createTable(greaterName, HConstants.CATALOG_FAMILY);
260 
261     // Now make sure we only get the regions from 1 of the tables at a time
262 
263     assertEquals(1, MetaTableAccessor.getTableRegions(UTIL.getZooKeeperWatcher(),
264       connection, name).size());
265     assertEquals(1, MetaTableAccessor.getTableRegions(UTIL.getZooKeeperWatcher(),
266       connection, greaterName).size());
267   }
268 
269   private static List<HRegionInfo> testGettingTableRegions(final Connection connection,
270       final TableName name, final int regionCount)
271   throws IOException, InterruptedException {
272     List<HRegionInfo> regions = MetaTableAccessor.getTableRegions(UTIL.getZooKeeperWatcher(),
273       connection, name);
274     assertEquals(regionCount, regions.size());
275     Pair<HRegionInfo, ServerName> pair =
276       MetaTableAccessor.getRegion(connection, regions.get(0).getRegionName());
277     assertEquals(regions.get(0).getEncodedName(),
278       pair.getFirst().getEncodedName());
279     return regions;
280   }
281 
282   private static void testGetRegion(final Connection connection,
283       final HRegionInfo region)
284   throws IOException, InterruptedException {
285     Pair<HRegionInfo, ServerName> pair =
286       MetaTableAccessor.getRegion(connection, region.getRegionName());
287     assertEquals(region.getEncodedName(),
288       pair.getFirst().getEncodedName());
289   }
290 
291   @Test
292   public void testParseReplicaIdFromServerColumn() {
293     String column1 = HConstants.SERVER_QUALIFIER_STR;
294     assertEquals(0, MetaTableAccessor.parseReplicaIdFromServerColumn(Bytes.toBytes(column1)));
295     String column2 = column1 + MetaTableAccessor.META_REPLICA_ID_DELIMITER;
296     assertEquals(-1, MetaTableAccessor.parseReplicaIdFromServerColumn(Bytes.toBytes(column2)));
297     String column3 = column2 + "00";
298     assertEquals(-1, MetaTableAccessor.parseReplicaIdFromServerColumn(Bytes.toBytes(column3)));
299     String column4 = column3 + "2A";
300     assertEquals(42, MetaTableAccessor.parseReplicaIdFromServerColumn(Bytes.toBytes(column4)));
301     String column5 = column4 + "2A";
302     assertEquals(-1, MetaTableAccessor.parseReplicaIdFromServerColumn(Bytes.toBytes(column5)));
303     String column6 = HConstants.STARTCODE_QUALIFIER_STR;
304     assertEquals(-1, MetaTableAccessor.parseReplicaIdFromServerColumn(Bytes.toBytes(column6)));
305   }
306 
307   @Test
308   public void testMetaReaderGetColumnMethods() {
309     Assert.assertArrayEquals(HConstants.SERVER_QUALIFIER, MetaTableAccessor.getServerColumn(0));
310     Assert.assertArrayEquals(Bytes.toBytes(HConstants.SERVER_QUALIFIER_STR
311       + MetaTableAccessor.META_REPLICA_ID_DELIMITER + "002A"),
312       MetaTableAccessor.getServerColumn(42));
313 
314     Assert.assertArrayEquals(HConstants.STARTCODE_QUALIFIER,
315       MetaTableAccessor.getStartCodeColumn(0));
316     Assert.assertArrayEquals(Bytes.toBytes(HConstants.STARTCODE_QUALIFIER_STR
317       + MetaTableAccessor.META_REPLICA_ID_DELIMITER + "002A"),
318       MetaTableAccessor.getStartCodeColumn(42));
319 
320     Assert.assertArrayEquals(HConstants.SEQNUM_QUALIFIER,
321       MetaTableAccessor.getSeqNumColumn(0));
322     Assert.assertArrayEquals(Bytes.toBytes(HConstants.SEQNUM_QUALIFIER_STR
323       + MetaTableAccessor.META_REPLICA_ID_DELIMITER + "002A"),
324       MetaTableAccessor.getSeqNumColumn(42));
325   }
326 
327   @Test
328   public void testMetaLocationsForRegionReplicas() throws IOException {
329     ServerName serverName0 = ServerName.valueOf("foo", 60010, random.nextLong());
330     ServerName serverName1 = ServerName.valueOf("bar", 60010, random.nextLong());
331     ServerName serverName100 = ServerName.valueOf("baz", 60010, random.nextLong());
332 
333     long regionId = System.currentTimeMillis();
334     HRegionInfo primary = new HRegionInfo(TableName.valueOf("table_foo"),
335       HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 0);
336     HRegionInfo replica1 = new HRegionInfo(TableName.valueOf("table_foo"),
337       HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 1);
338     HRegionInfo replica100 = new HRegionInfo(TableName.valueOf("table_foo"),
339       HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 100);
340 
341     long seqNum0 = random.nextLong();
342     long seqNum1 = random.nextLong();
343     long seqNum100 = random.nextLong();
344 
345 
346     Table meta = MetaTableAccessor.getMetaHTable(connection);
347     try {
348       MetaTableAccessor.updateRegionLocation(connection, primary, serverName0, seqNum0, -1);
349 
350       // assert that the server, startcode and seqNum columns are there for the primary region
351       assertMetaLocation(meta, primary.getRegionName(), serverName0, seqNum0, 0, true);
352 
353       // add replica = 1
354       MetaTableAccessor.updateRegionLocation(connection, replica1, serverName1, seqNum1, -1);
355       // check whether the primary is still there
356       assertMetaLocation(meta, primary.getRegionName(), serverName0, seqNum0, 0, true);
357       // now check for replica 1
358       assertMetaLocation(meta, primary.getRegionName(), serverName1, seqNum1, 1, true);
359 
360       // add replica = 1
361       MetaTableAccessor.updateRegionLocation(connection, replica100, serverName100, seqNum100, -1);
362       // check whether the primary is still there
363       assertMetaLocation(meta, primary.getRegionName(), serverName0, seqNum0, 0, true);
364       // check whether the replica 1 is still there
365       assertMetaLocation(meta, primary.getRegionName(), serverName1, seqNum1, 1, true);
366       // now check for replica 1
367       assertMetaLocation(meta, primary.getRegionName(), serverName100, seqNum100, 100, true);
368     } finally {
369       meta.close();
370     }
371   }
372 
373   public static void assertMetaLocation(Table meta, byte[] row, ServerName serverName,
374       long seqNum, int replicaId, boolean checkSeqNum) throws IOException {
375     Get get = new Get(row);
376     Result result = meta.get(get);
377     assertTrue(Bytes.equals(
378       result.getValue(HConstants.CATALOG_FAMILY, MetaTableAccessor.getServerColumn(replicaId)),
379       Bytes.toBytes(serverName.getHostAndPort())));
380     assertTrue(Bytes.equals(
381       result.getValue(HConstants.CATALOG_FAMILY, MetaTableAccessor.getStartCodeColumn(replicaId)),
382       Bytes.toBytes(serverName.getStartcode())));
383     if (checkSeqNum) {
384       assertTrue(Bytes.equals(
385         result.getValue(HConstants.CATALOG_FAMILY, MetaTableAccessor.getSeqNumColumn(replicaId)),
386         Bytes.toBytes(seqNum)));
387     }
388   }
389 
390   public static void assertEmptyMetaLocation(Table meta, byte[] row, int replicaId)
391       throws IOException {
392     Get get = new Get(row);
393     Result result = meta.get(get);
394     Cell serverCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
395       MetaTableAccessor.getServerColumn(replicaId));
396     Cell startCodeCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
397       MetaTableAccessor.getStartCodeColumn(replicaId));
398     assertNotNull(serverCell);
399     assertNotNull(startCodeCell);
400     assertEquals(0, serverCell.getValueLength());
401     assertEquals(0, startCodeCell.getValueLength());
402   }
403 
404   @Test
405   public void testMetaLocationForRegionReplicasIsAddedAtTableCreation() throws IOException {
406     long regionId = System.currentTimeMillis();
407     HRegionInfo primary = new HRegionInfo(TableName.valueOf("table_foo"),
408       HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 0);
409 
410     Table meta = MetaTableAccessor.getMetaHTable(connection);
411     try {
412       List<HRegionInfo> regionInfos = Lists.newArrayList(primary);
413       MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 3);
414 
415       assertEmptyMetaLocation(meta, primary.getRegionName(), 1);
416       assertEmptyMetaLocation(meta, primary.getRegionName(), 2);
417     } finally {
418       meta.close();
419     }
420   }
421 
422   @Test
423   public void testMetaLocationForRegionReplicasIsAddedAtRegionSplit() throws IOException {
424     long regionId = System.currentTimeMillis();
425     ServerName serverName0 = ServerName.valueOf("foo", 60010, random.nextLong());
426     HRegionInfo parent = new HRegionInfo(TableName.valueOf("table_foo"),
427       HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 0);
428     HRegionInfo splitA = new HRegionInfo(TableName.valueOf("table_foo"),
429       HConstants.EMPTY_START_ROW, Bytes.toBytes("a"), false, regionId+1, 0);
430     HRegionInfo splitB = new HRegionInfo(TableName.valueOf("table_foo"),
431       Bytes.toBytes("a"), HConstants.EMPTY_END_ROW, false, regionId+1, 0);
432 
433 
434     Table meta = MetaTableAccessor.getMetaHTable(connection);
435     try {
436       List<HRegionInfo> regionInfos = Lists.newArrayList(parent);
437       MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 3);
438 
439       MetaTableAccessor.splitRegion(connection, parent, splitA, splitB, serverName0, 3);
440 
441       assertEmptyMetaLocation(meta, splitA.getRegionName(), 1);
442       assertEmptyMetaLocation(meta, splitA.getRegionName(), 2);
443       assertEmptyMetaLocation(meta, splitB.getRegionName(), 1);
444       assertEmptyMetaLocation(meta, splitB.getRegionName(), 2);
445     } finally {
446       meta.close();
447     }
448   }
449 
450   @Test
451   public void testMetaLocationForRegionReplicasIsAddedAtRegionMerge() throws IOException {
452     long regionId = System.currentTimeMillis();
453     ServerName serverName0 = ServerName.valueOf("foo", 60010, random.nextLong());
454 
455     HRegionInfo parentA = new HRegionInfo(TableName.valueOf("table_foo"),
456       Bytes.toBytes("a"), HConstants.EMPTY_END_ROW, false, regionId, 0);
457     HRegionInfo parentB = new HRegionInfo(TableName.valueOf("table_foo"),
458       HConstants.EMPTY_START_ROW, Bytes.toBytes("a"), false, regionId, 0);
459     HRegionInfo merged = new HRegionInfo(TableName.valueOf("table_foo"),
460       HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId+1, 0);
461 
462     Table meta = MetaTableAccessor.getMetaHTable(connection);
463     try {
464       List<HRegionInfo> regionInfos = Lists.newArrayList(parentA, parentB);
465       MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 3);
466 
467       MetaTableAccessor.mergeRegions(connection, merged, parentA, parentB, serverName0, 3,
468           HConstants.LATEST_TIMESTAMP);
469 
470       assertEmptyMetaLocation(meta, merged.getRegionName(), 1);
471       assertEmptyMetaLocation(meta, merged.getRegionName(), 2);
472     } finally {
473       meta.close();
474     }
475   }
476 
477   /**
478    * Tests whether maximum of masters system time versus RSs local system time is used
479    */
480   @Test
481   public void testMastersSystemTimeIsUsedInUpdateLocations() throws IOException {
482     long regionId = System.currentTimeMillis();
483     HRegionInfo regionInfo = new HRegionInfo(TableName.valueOf("table_foo"),
484       HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 0);
485 
486     ServerName sn = ServerName.valueOf("bar", 0, 0);
487     Table meta = MetaTableAccessor.getMetaHTable(connection);
488     try {
489       List<HRegionInfo> regionInfos = Lists.newArrayList(regionInfo);
490       MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 1);
491 
492       long masterSystemTime = EnvironmentEdgeManager.currentTime() + 123456789;
493       MetaTableAccessor.updateRegionLocation(connection, regionInfo, sn, 1, masterSystemTime);
494 
495       Get get = new Get(regionInfo.getRegionName());
496       Result result = meta.get(get);
497       Cell serverCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
498           MetaTableAccessor.getServerColumn(0));
499       Cell startCodeCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
500         MetaTableAccessor.getStartCodeColumn(0));
501       Cell seqNumCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
502         MetaTableAccessor.getSeqNumColumn(0));
503       assertNotNull(serverCell);
504       assertNotNull(startCodeCell);
505       assertNotNull(seqNumCell);
506       assertTrue(serverCell.getValueLength() > 0);
507       assertTrue(startCodeCell.getValueLength() > 0);
508       assertTrue(seqNumCell.getValueLength() > 0);
509       assertEquals(masterSystemTime, serverCell.getTimestamp());
510       assertEquals(masterSystemTime, startCodeCell.getTimestamp());
511       assertEquals(masterSystemTime, seqNumCell.getTimestamp());
512     } finally {
513       meta.close();
514     }
515   }
516 
517   @Test
518   public void testMastersSystemTimeIsUsedInMergeRegions() throws IOException {
519     long regionId = System.currentTimeMillis();
520     HRegionInfo regionInfoA = new HRegionInfo(TableName.valueOf("table_foo"),
521       HConstants.EMPTY_START_ROW, new byte[] {'a'}, false, regionId, 0);
522     HRegionInfo regionInfoB = new HRegionInfo(TableName.valueOf("table_foo"),
523       new byte[] {'a'}, HConstants.EMPTY_END_ROW, false, regionId, 0);
524     HRegionInfo mergedRegionInfo = new HRegionInfo(TableName.valueOf("table_foo"),
525       HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 0);
526 
527     ServerName sn = ServerName.valueOf("bar", 0, 0);
528     Table meta = MetaTableAccessor.getMetaHTable(connection);
529     try {
530       List<HRegionInfo> regionInfos = Lists.newArrayList(regionInfoA, regionInfoB);
531       MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 1);
532 
533       // write the serverName column with a big current time, but set the masters time as even
534       // bigger. When region merge deletes the rows for regionA and regionB, the serverName columns
535       // should not be seen by the following get
536       long serverNameTime = EnvironmentEdgeManager.currentTime()   + 100000000;
537       long masterSystemTime = EnvironmentEdgeManager.currentTime() + 123456789;
538 
539       // write the serverName columns
540       MetaTableAccessor.updateRegionLocation(connection, regionInfoA, sn, 1, serverNameTime);
541 
542       // assert that we have the serverName column with expected ts
543       Get get = new Get(mergedRegionInfo.getRegionName());
544       Result result = meta.get(get);
545       Cell serverCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
546           MetaTableAccessor.getServerColumn(0));
547       assertNotNull(serverCell);
548       assertEquals(serverNameTime, serverCell.getTimestamp());
549 
550       // now merge the regions, effectively deleting the rows for region a and b.
551       MetaTableAccessor.mergeRegions(connection, mergedRegionInfo,
552         regionInfoA, regionInfoB, sn, 1, masterSystemTime);
553 
554       result = meta.get(get);
555       serverCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
556           MetaTableAccessor.getServerColumn(0));
557       Cell startCodeCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
558         MetaTableAccessor.getStartCodeColumn(0));
559       Cell seqNumCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
560         MetaTableAccessor.getSeqNumColumn(0));
561       assertNull(serverCell);
562       assertNull(startCodeCell);
563       assertNull(seqNumCell);
564     } finally {
565       meta.close();
566     }
567   }
568 }
569