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.junit.jupiter.api.Assertions.assertEquals; 021import static org.junit.jupiter.api.Assertions.fail; 022 023import java.io.IOException; 024import java.util.ArrayList; 025import java.util.Collections; 026import java.util.HashMap; 027import java.util.HashSet; 028import java.util.Iterator; 029import java.util.List; 030import java.util.Map; 031import java.util.Random; 032import java.util.Set; 033import java.util.concurrent.ThreadLocalRandom; 034import java.util.concurrent.atomic.AtomicBoolean; 035import org.apache.hadoop.conf.Configuration; 036import org.apache.hadoop.fs.FileSystem; 037import org.apache.hadoop.fs.FileUtil; 038import org.apache.hadoop.fs.Path; 039import org.apache.hadoop.hbase.ExtendedCell; 040import org.apache.hadoop.hbase.HBaseTestingUtil; 041import org.apache.hadoop.hbase.HConstants; 042import org.apache.hadoop.hbase.KeyValue; 043import org.apache.hadoop.hbase.PrivateCellUtil; 044import org.apache.hadoop.hbase.Stoppable; 045import org.apache.hadoop.hbase.TableName; 046import org.apache.hadoop.hbase.TableNotFoundException; 047import org.apache.hadoop.hbase.client.Admin; 048import org.apache.hadoop.hbase.client.Connection; 049import org.apache.hadoop.hbase.client.ConnectionFactory; 050import org.apache.hadoop.hbase.client.Get; 051import org.apache.hadoop.hbase.client.RegionInfo; 052import org.apache.hadoop.hbase.client.RegionLocator; 053import org.apache.hadoop.hbase.client.Result; 054import org.apache.hadoop.hbase.client.ResultScanner; 055import org.apache.hadoop.hbase.client.RetriesExhaustedException; 056import org.apache.hadoop.hbase.client.Scan; 057import org.apache.hadoop.hbase.client.Table; 058import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost; 059import org.apache.hadoop.hbase.testclassification.LargeTests; 060import org.apache.hadoop.hbase.testclassification.ReplicationTests; 061import org.apache.hadoop.hbase.util.Bytes; 062import org.apache.hadoop.hbase.util.CommonFSUtils; 063import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 064import org.apache.hadoop.hbase.util.HFileTestUtil; 065import org.apache.hadoop.hbase.wal.WALEditInternalHelper; 066import org.junit.jupiter.api.AfterAll; 067import org.junit.jupiter.api.BeforeAll; 068import org.junit.jupiter.api.BeforeEach; 069import org.junit.jupiter.api.Tag; 070import org.junit.jupiter.api.Test; 071import org.slf4j.Logger; 072import org.slf4j.LoggerFactory; 073 074import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations; 075 076import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 077import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.WALEntry; 078import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.UUID; 079import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos; 080import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.WALKey; 081 082@Tag(ReplicationTests.TAG) 083@Tag(LargeTests.TAG) 084public class TestReplicationSink { 085 086 private static final Logger LOG = LoggerFactory.getLogger(TestReplicationSink.class); 087 private static final int BATCH_SIZE = 10; 088 089 protected final static HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 090 091 protected static ReplicationSink SINK; 092 093 protected static final TableName TABLE_NAME1 = TableName.valueOf("table1"); 094 protected static final TableName TABLE_NAME2 = TableName.valueOf("table2"); 095 096 protected static final byte[] FAM_NAME1 = Bytes.toBytes("info1"); 097 protected static final byte[] FAM_NAME2 = Bytes.toBytes("info2"); 098 099 protected static Table table1; 100 protected static Stoppable STOPPABLE = new Stoppable() { 101 final AtomicBoolean stop = new AtomicBoolean(false); 102 103 @Override 104 public boolean isStopped() { 105 return this.stop.get(); 106 } 107 108 @Override 109 public void stop(String why) { 110 LOG.info("STOPPING BECAUSE: " + why); 111 this.stop.set(true); 112 } 113 114 }; 115 116 protected static Table table2; 117 protected static String baseNamespaceDir; 118 protected static String hfileArchiveDir; 119 protected static String replicationClusterId; 120 121 @BeforeAll 122 public static void setUpBeforeClass() throws Exception { 123 TEST_UTIL.getConfiguration().set("hbase.replication.source.fs.conf.provider", 124 TestSourceFSConfigurationProvider.class.getCanonicalName()); 125 TEST_UTIL.startMiniCluster(3); 126 RegionServerCoprocessorHost rsCpHost = 127 TEST_UTIL.getMiniHBaseCluster().getRegionServer(0).getRegionServerCoprocessorHost(); 128 SINK = new ReplicationSink(new Configuration(TEST_UTIL.getConfiguration()), rsCpHost); 129 table1 = TEST_UTIL.createTable(TABLE_NAME1, FAM_NAME1); 130 table2 = TEST_UTIL.createTable(TABLE_NAME2, FAM_NAME2); 131 Path rootDir = CommonFSUtils.getRootDir(TEST_UTIL.getConfiguration()); 132 baseNamespaceDir = new Path(rootDir, new Path(HConstants.BASE_NAMESPACE_DIR)).toString(); 133 hfileArchiveDir = new Path(rootDir, new Path(HConstants.HFILE_ARCHIVE_DIRECTORY)).toString(); 134 replicationClusterId = "12345"; 135 } 136 137 @AfterAll 138 public static void tearDownAfterClass() throws Exception { 139 STOPPABLE.stop("Shutting down"); 140 TEST_UTIL.shutdownMiniCluster(); 141 } 142 143 @BeforeEach 144 public void setUp() throws Exception { 145 table1 = TEST_UTIL.deleteTableData(TABLE_NAME1); 146 table2 = TEST_UTIL.deleteTableData(TABLE_NAME2); 147 } 148 149 /** 150 * Insert a whole batch of entries 151 */ 152 @Test 153 public void testBatchSink() throws Exception { 154 List<WALEntry> entries = new ArrayList<>(BATCH_SIZE); 155 List<ExtendedCell> cells = new ArrayList<>(); 156 for (int i = 0; i < BATCH_SIZE; i++) { 157 entries.add(createEntry(TABLE_NAME1, i, KeyValue.Type.Put, cells)); 158 } 159 SINK.replicateEntries(entries, PrivateCellUtil.createExtendedCellScanner(cells.iterator()), 160 replicationClusterId, baseNamespaceDir, hfileArchiveDir); 161 Scan scan = new Scan(); 162 ResultScanner scanRes = table1.getScanner(scan); 163 assertEquals(BATCH_SIZE, scanRes.next(BATCH_SIZE).length); 164 } 165 166 /** 167 * Insert a mix of puts and deletes 168 */ 169 @Test 170 public void testMixedPutDelete() throws Exception { 171 List<WALEntry> entries = new ArrayList<>(BATCH_SIZE / 2); 172 List<ExtendedCell> cells = new ArrayList<>(); 173 for (int i = 0; i < BATCH_SIZE / 2; i++) { 174 entries.add(createEntry(TABLE_NAME1, i, KeyValue.Type.Put, cells)); 175 } 176 SINK.replicateEntries(entries, PrivateCellUtil.createExtendedCellScanner(cells), 177 replicationClusterId, baseNamespaceDir, hfileArchiveDir); 178 179 entries = new ArrayList<>(BATCH_SIZE); 180 cells = new ArrayList<>(); 181 for (int i = 0; i < BATCH_SIZE; i++) { 182 entries.add(createEntry(TABLE_NAME1, i, 183 i % 2 != 0 ? KeyValue.Type.Put : KeyValue.Type.DeleteColumn, cells)); 184 } 185 186 SINK.replicateEntries(entries, PrivateCellUtil.createExtendedCellScanner(cells.iterator()), 187 replicationClusterId, baseNamespaceDir, hfileArchiveDir); 188 Scan scan = new Scan(); 189 ResultScanner scanRes = table1.getScanner(scan); 190 assertEquals(BATCH_SIZE / 2, scanRes.next(BATCH_SIZE).length); 191 } 192 193 @Test 194 public void testLargeEditsPutDelete() throws Exception { 195 List<WALEntry> entries = new ArrayList<>(); 196 List<ExtendedCell> cells = new ArrayList<>(); 197 for (int i = 0; i < 5510; i++) { 198 entries.add(createEntry(TABLE_NAME1, i, KeyValue.Type.Put, cells)); 199 } 200 SINK.replicateEntries(entries, PrivateCellUtil.createExtendedCellScanner(cells), 201 replicationClusterId, baseNamespaceDir, hfileArchiveDir); 202 203 ResultScanner resultScanner = table1.getScanner(new Scan()); 204 int totalRows = 0; 205 while (resultScanner.next() != null) { 206 totalRows++; 207 } 208 assertEquals(5510, totalRows); 209 210 entries = new ArrayList<>(); 211 cells = new ArrayList<>(); 212 for (int i = 0; i < 11000; i++) { 213 entries.add(createEntry(TABLE_NAME1, i, 214 i % 2 != 0 ? KeyValue.Type.Put : KeyValue.Type.DeleteColumn, cells)); 215 } 216 SINK.replicateEntries(entries, PrivateCellUtil.createExtendedCellScanner(cells), 217 replicationClusterId, baseNamespaceDir, hfileArchiveDir); 218 resultScanner = table1.getScanner(new Scan()); 219 totalRows = 0; 220 while (resultScanner.next() != null) { 221 totalRows++; 222 } 223 assertEquals(5500, totalRows); 224 } 225 226 /** 227 * Insert to 2 different tables 228 */ 229 @Test 230 public void testMixedPutTables() throws Exception { 231 List<WALEntry> entries = new ArrayList<>(BATCH_SIZE / 2); 232 List<ExtendedCell> cells = new ArrayList<>(); 233 for (int i = 0; i < BATCH_SIZE; i++) { 234 entries.add(createEntry(i % 2 == 0 ? TABLE_NAME2 : TABLE_NAME1, i, KeyValue.Type.Put, cells)); 235 } 236 237 SINK.replicateEntries(entries, PrivateCellUtil.createExtendedCellScanner(cells.iterator()), 238 replicationClusterId, baseNamespaceDir, hfileArchiveDir); 239 Scan scan = new Scan(); 240 ResultScanner scanRes = table2.getScanner(scan); 241 for (Result res : scanRes) { 242 assertEquals(0, Bytes.toInt(res.getRow()) % 2); 243 } 244 scanRes = table1.getScanner(scan); 245 for (Result res : scanRes) { 246 assertEquals(1, Bytes.toInt(res.getRow()) % 2); 247 } 248 } 249 250 /** 251 * Insert then do different types of deletes 252 */ 253 @Test 254 public void testMixedDeletes() throws Exception { 255 List<WALEntry> entries = new ArrayList<>(3); 256 List<ExtendedCell> cells = new ArrayList<>(); 257 for (int i = 0; i < 3; i++) { 258 entries.add(createEntry(TABLE_NAME1, i, KeyValue.Type.Put, cells)); 259 } 260 SINK.replicateEntries(entries, PrivateCellUtil.createExtendedCellScanner(cells.iterator()), 261 replicationClusterId, baseNamespaceDir, hfileArchiveDir); 262 entries = new ArrayList<>(3); 263 cells = new ArrayList<>(); 264 entries.add(createEntry(TABLE_NAME1, 0, KeyValue.Type.DeleteColumn, cells)); 265 entries.add(createEntry(TABLE_NAME1, 1, KeyValue.Type.DeleteFamily, cells)); 266 entries.add(createEntry(TABLE_NAME1, 2, KeyValue.Type.DeleteColumn, cells)); 267 268 SINK.replicateEntries(entries, PrivateCellUtil.createExtendedCellScanner(cells.iterator()), 269 replicationClusterId, baseNamespaceDir, hfileArchiveDir); 270 271 Scan scan = new Scan(); 272 ResultScanner scanRes = table1.getScanner(scan); 273 assertEquals(0, scanRes.next(3).length); 274 } 275 276 /** 277 * Puts are buffered, but this tests when a delete (not-buffered) is applied before the actual Put 278 * that creates it. 279 */ 280 @Test 281 public void testApplyDeleteBeforePut() throws Exception { 282 List<WALEntry> entries = new ArrayList<>(5); 283 List<ExtendedCell> cells = new ArrayList<>(); 284 for (int i = 0; i < 2; i++) { 285 entries.add(createEntry(TABLE_NAME1, i, KeyValue.Type.Put, cells)); 286 } 287 entries.add(createEntry(TABLE_NAME1, 1, KeyValue.Type.DeleteFamily, cells)); 288 for (int i = 3; i < 5; i++) { 289 entries.add(createEntry(TABLE_NAME1, i, KeyValue.Type.Put, cells)); 290 } 291 SINK.replicateEntries(entries, PrivateCellUtil.createExtendedCellScanner(cells.iterator()), 292 replicationClusterId, baseNamespaceDir, hfileArchiveDir); 293 Get get = new Get(Bytes.toBytes(1)); 294 Result res = table1.get(get); 295 assertEquals(0, res.size()); 296 } 297 298 @Test 299 public void testRethrowRetriesExhaustedException() throws Exception { 300 TableName notExistTable = TableName.valueOf("notExistTable"); 301 List<WALEntry> entries = new ArrayList<>(); 302 List<ExtendedCell> cells = new ArrayList<>(); 303 for (int i = 0; i < 10; i++) { 304 entries.add(createEntry(notExistTable, i, KeyValue.Type.Put, cells)); 305 } 306 try { 307 SINK.replicateEntries(entries, PrivateCellUtil.createExtendedCellScanner(cells.iterator()), 308 replicationClusterId, baseNamespaceDir, hfileArchiveDir); 309 fail("Should re-throw TableNotFoundException."); 310 } catch (TableNotFoundException e) { 311 } 312 entries.clear(); 313 cells.clear(); 314 for (int i = 0; i < 10; i++) { 315 entries.add(createEntry(TABLE_NAME1, i, KeyValue.Type.Put, cells)); 316 } 317 try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration())) { 318 try (Admin admin = conn.getAdmin()) { 319 admin.disableTable(TABLE_NAME1); 320 try { 321 SINK.replicateEntries(entries, 322 PrivateCellUtil.createExtendedCellScanner(cells.iterator()), replicationClusterId, 323 baseNamespaceDir, hfileArchiveDir); 324 fail("Should re-throw RetriesExhaustedWithDetailsException."); 325 } catch (RetriesExhaustedException e) { 326 } finally { 327 admin.enableTable(TABLE_NAME1); 328 } 329 } 330 } 331 } 332 333 /** 334 * Test replicateEntries with a bulk load entry for 25 HFiles 335 */ 336 @Test 337 public void testReplicateEntriesForHFiles() throws Exception { 338 Path dir = TEST_UTIL.getDataTestDirOnTestFS("testReplicateEntries"); 339 Path familyDir = new Path(dir, Bytes.toString(FAM_NAME1)); 340 int numRows = 10; 341 List<Path> p = new ArrayList<>(1); 342 final String hfilePrefix = "hfile-"; 343 344 // 1. Generate 25 hfile ranges 345 Random rand = ThreadLocalRandom.current(); 346 Set<Integer> numbers = new HashSet<>(); 347 while (numbers.size() < 50) { 348 numbers.add(rand.nextInt(1000)); 349 } 350 List<Integer> numberList = new ArrayList<>(numbers); 351 Collections.sort(numberList); 352 Map<String, Long> storeFilesSize = new HashMap<>(1); 353 354 // 2. Create 25 hfiles 355 Configuration conf = TEST_UTIL.getConfiguration(); 356 FileSystem fs = dir.getFileSystem(conf); 357 Iterator<Integer> numbersItr = numberList.iterator(); 358 for (int i = 0; i < 25; i++) { 359 Path hfilePath = new Path(familyDir, hfilePrefix + i); 360 HFileTestUtil.createHFile(conf, fs, hfilePath, FAM_NAME1, FAM_NAME1, 361 Bytes.toBytes(numbersItr.next()), Bytes.toBytes(numbersItr.next()), numRows); 362 p.add(hfilePath); 363 storeFilesSize.put(hfilePath.getName(), fs.getFileStatus(hfilePath).getLen()); 364 } 365 366 // 3. Create a BulkLoadDescriptor and a WALEdit 367 Map<byte[], List<Path>> storeFiles = new HashMap<>(1); 368 storeFiles.put(FAM_NAME1, p); 369 org.apache.hadoop.hbase.wal.WALEdit edit = null; 370 WALProtos.BulkLoadDescriptor loadDescriptor = null; 371 372 try (Connection c = ConnectionFactory.createConnection(conf); 373 RegionLocator l = c.getRegionLocator(TABLE_NAME1)) { 374 RegionInfo regionInfo = l.getAllRegionLocations().get(0).getRegion(); 375 loadDescriptor = ProtobufUtil.toBulkLoadDescriptor(TABLE_NAME1, 376 UnsafeByteOperations.unsafeWrap(regionInfo.getEncodedNameAsBytes()), storeFiles, 377 storeFilesSize, 1); 378 edit = org.apache.hadoop.hbase.wal.WALEdit.createBulkLoadEvent(regionInfo, loadDescriptor); 379 } 380 List<WALEntry> entries = new ArrayList<>(1); 381 382 // 4. Create a WALEntryBuilder 383 WALEntry.Builder builder = createWALEntryBuilder(TABLE_NAME1); 384 385 // 5. Copy the hfile to the path as it is in reality 386 for (int i = 0; i < 25; i++) { 387 String pathToHfileFromNS = new StringBuilder(100).append(TABLE_NAME1.getNamespaceAsString()) 388 .append(Path.SEPARATOR).append(Bytes.toString(TABLE_NAME1.getName())).append(Path.SEPARATOR) 389 .append(Bytes.toString(loadDescriptor.getEncodedRegionName().toByteArray())) 390 .append(Path.SEPARATOR).append(Bytes.toString(FAM_NAME1)).append(Path.SEPARATOR) 391 .append(hfilePrefix + i).toString(); 392 String dst = baseNamespaceDir + Path.SEPARATOR + pathToHfileFromNS; 393 Path dstPath = new Path(dst); 394 FileUtil.copy(fs, p.get(0), fs, dstPath, false, conf); 395 } 396 397 entries.add(builder.build()); 398 try (ResultScanner scanner = table1.getScanner(new Scan())) { 399 // 6. Assert no existing data in table 400 assertEquals(0, scanner.next(numRows).length); 401 } 402 // 7. Replicate the bulk loaded entry 403 SINK.replicateEntries(entries, 404 PrivateCellUtil 405 .createExtendedCellScanner(WALEditInternalHelper.getExtendedCells(edit).iterator()), 406 replicationClusterId, baseNamespaceDir, hfileArchiveDir); 407 try (ResultScanner scanner = table1.getScanner(new Scan())) { 408 // 8. Assert data is replicated 409 assertEquals(numRows, scanner.next(numRows).length); 410 } 411 // Clean up the created hfiles or it will mess up subsequent tests 412 } 413 414 /** 415 * Test failure metrics produced for failed replication edits 416 */ 417 @Test 418 public void testFailedReplicationSinkMetrics() throws IOException { 419 long initialFailedBatches = SINK.getSinkMetrics().getFailedBatches(); 420 long errorCount = 0L; 421 List<WALEntry> entries = new ArrayList<>(BATCH_SIZE); 422 List<ExtendedCell> cells = new ArrayList<>(); 423 for (int i = 0; i < BATCH_SIZE; i++) { 424 entries.add(createEntry(TABLE_NAME1, i, KeyValue.Type.Put, cells)); 425 } 426 cells.clear(); // cause IndexOutOfBoundsException 427 try { 428 SINK.replicateEntries(entries, PrivateCellUtil.createExtendedCellScanner(cells.iterator()), 429 replicationClusterId, baseNamespaceDir, hfileArchiveDir); 430 fail("Should re-throw ArrayIndexOutOfBoundsException."); 431 } catch (ArrayIndexOutOfBoundsException e) { 432 errorCount++; 433 assertEquals(initialFailedBatches + errorCount, SINK.getSinkMetrics().getFailedBatches()); 434 } 435 436 entries.clear(); 437 cells.clear(); 438 TableName notExistTable = TableName.valueOf("notExistTable"); // cause TableNotFoundException 439 for (int i = 0; i < BATCH_SIZE; i++) { 440 entries.add(createEntry(notExistTable, i, KeyValue.Type.Put, cells)); 441 } 442 try { 443 SINK.replicateEntries(entries, PrivateCellUtil.createExtendedCellScanner(cells.iterator()), 444 replicationClusterId, baseNamespaceDir, hfileArchiveDir); 445 fail("Should re-throw TableNotFoundException."); 446 } catch (TableNotFoundException e) { 447 errorCount++; 448 assertEquals(initialFailedBatches + errorCount, SINK.getSinkMetrics().getFailedBatches()); 449 } 450 451 entries.clear(); 452 cells.clear(); 453 for (int i = 0; i < BATCH_SIZE; i++) { 454 entries.add(createEntry(TABLE_NAME1, i, KeyValue.Type.Put, cells)); 455 } 456 // cause IOException in batch() 457 try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration())) { 458 try (Admin admin = conn.getAdmin()) { 459 admin.disableTable(TABLE_NAME1); 460 try { 461 SINK.replicateEntries(entries, 462 PrivateCellUtil.createExtendedCellScanner(cells.iterator()), replicationClusterId, 463 baseNamespaceDir, hfileArchiveDir); 464 fail("Should re-throw IOException."); 465 } catch (IOException e) { 466 errorCount++; 467 assertEquals(initialFailedBatches + errorCount, SINK.getSinkMetrics().getFailedBatches()); 468 } finally { 469 admin.enableTable(TABLE_NAME1); 470 } 471 } 472 } 473 } 474 475 private WALEntry createEntry(TableName table, int row, KeyValue.Type type, 476 List<ExtendedCell> cells) { 477 byte[] fam = table.equals(TABLE_NAME1) ? FAM_NAME1 : FAM_NAME2; 478 byte[] rowBytes = Bytes.toBytes(row); 479 // Just make sure we don't get the same ts for two consecutive rows with 480 // same key 481 try { 482 Thread.sleep(1); 483 } catch (InterruptedException e) { 484 LOG.info("Was interrupted while sleep, meh", e); 485 } 486 final long now = EnvironmentEdgeManager.currentTime(); 487 KeyValue kv = null; 488 if (type.getCode() == KeyValue.Type.Put.getCode()) { 489 kv = new KeyValue(rowBytes, fam, fam, now, KeyValue.Type.Put, Bytes.toBytes(row)); 490 } else if (type.getCode() == KeyValue.Type.DeleteColumn.getCode()) { 491 kv = new KeyValue(rowBytes, fam, fam, now, KeyValue.Type.DeleteColumn); 492 } else if (type.getCode() == KeyValue.Type.DeleteFamily.getCode()) { 493 kv = new KeyValue(rowBytes, fam, null, now, KeyValue.Type.DeleteFamily); 494 } 495 WALEntry.Builder builder = createWALEntryBuilder(table); 496 cells.add(kv); 497 498 return builder.build(); 499 } 500 501 public static WALEntry.Builder createWALEntryBuilder(TableName table) { 502 WALEntry.Builder builder = WALEntry.newBuilder(); 503 builder.setAssociatedCellCount(1); 504 WALKey.Builder keyBuilder = WALKey.newBuilder(); 505 UUID.Builder uuidBuilder = UUID.newBuilder(); 506 uuidBuilder.setLeastSigBits(HConstants.DEFAULT_CLUSTER_ID.getLeastSignificantBits()); 507 uuidBuilder.setMostSigBits(HConstants.DEFAULT_CLUSTER_ID.getMostSignificantBits()); 508 keyBuilder.setClusterId(uuidBuilder.build()); 509 keyBuilder.setTableName(UnsafeByteOperations.unsafeWrap(table.getName())); 510 keyBuilder.setWriteTime(EnvironmentEdgeManager.currentTime()); 511 keyBuilder.setEncodedRegionName(UnsafeByteOperations.unsafeWrap(HConstants.EMPTY_BYTE_ARRAY)); 512 keyBuilder.setLogSequenceNumber(-1); 513 builder.setKey(keyBuilder.build()); 514 return builder; 515 } 516}