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.snapshot;
019
020import static org.junit.jupiter.api.Assertions.assertArrayEquals;
021import static org.junit.jupiter.api.Assertions.assertEquals;
022
023import java.io.IOException;
024import java.util.List;
025import org.apache.hadoop.conf.Configuration;
026import org.apache.hadoop.fs.FSDataOutputStream;
027import org.apache.hadoop.fs.FileSystem;
028import org.apache.hadoop.fs.Path;
029import org.apache.hadoop.hbase.HBaseTestingUtil;
030import org.apache.hadoop.hbase.HConstants;
031import org.apache.hadoop.hbase.HRegionLocation;
032import org.apache.hadoop.hbase.TableName;
033import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
034import org.apache.hadoop.hbase.client.RegionInfo;
035import org.apache.hadoop.hbase.client.RegionInfoBuilder;
036import org.apache.hadoop.hbase.client.TableDescriptor;
037import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
038import org.apache.hadoop.hbase.testclassification.MasterTests;
039import org.apache.hadoop.hbase.testclassification.SmallTests;
040import org.apache.hadoop.hbase.util.Bytes;
041import org.junit.jupiter.api.AfterEach;
042import org.junit.jupiter.api.BeforeEach;
043import org.junit.jupiter.api.Tag;
044import org.junit.jupiter.api.Test;
045
046import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
047import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDataManifest;
048import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription;
049import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;
050
051@Tag(MasterTests.TAG)
052@Tag(SmallTests.TAG)
053public class TestSnapshotRegionLocator {
054
055  private static final TableName TABLE_NAME = TableName.valueOf("testSnapshotRegionLocator");
056  private static final byte[] SPLIT_KEY = Bytes.toBytes("m");
057  private static final TableDescriptor TABLE_DESCRIPTOR = TableDescriptorBuilder
058    .newBuilder(TABLE_NAME).setColumnFamily(ColumnFamilyDescriptorBuilder.of("cf")).build();
059
060  private Configuration conf;
061  private FileSystem fs;
062  private Path rootDir;
063  private Path snapshotDir;
064
065  @BeforeEach
066  public void setUp() throws IOException {
067    HBaseTestingUtil testUtil = new HBaseTestingUtil();
068    conf = testUtil.getConfiguration();
069    fs = testUtil.getTestFileSystem();
070    rootDir = testUtil.getDataTestDir(TABLE_NAME.getNameAsString());
071    snapshotDir = new Path(rootDir, "snapshot");
072    fs.mkdirs(snapshotDir);
073
074    SnapshotDescription snapshot =
075      SnapshotDescription.newBuilder().setName("snapshot").setTable(TABLE_NAME.getNameAsString())
076        .setVersion(SnapshotManifestV2.DESCRIPTOR_VERSION).build();
077    SnapshotDescriptionUtils.writeSnapshotInfo(snapshot, snapshotDir, fs);
078    writeManifest();
079    SnapshotRegionLocator.setSnapshotManifestDir(conf, snapshotDir.toString(), TABLE_NAME);
080  }
081
082  @AfterEach
083  public void tearDown() throws IOException {
084    fs.delete(rootDir, true);
085  }
086
087  @Test
088  public void testFiltersOfflineAndSplitRegions() throws IOException {
089    try (SnapshotRegionLocator locator = SnapshotRegionLocator.create(conf, TABLE_NAME)) {
090      List<HRegionLocation> locations = locator.getAllRegionLocations();
091      assertEquals(2, locations.size());
092      assertEquals(1, locations.get(0).getRegion().getRegionId());
093      assertEquals(2, locations.get(1).getRegion().getRegionId());
094
095      byte[][] startKeys = locator.getStartKeys();
096      assertEquals(2, startKeys.length);
097      assertArrayEquals(HConstants.EMPTY_START_ROW, startKeys[0]);
098      assertArrayEquals(SPLIT_KEY, startKeys[1]);
099
100      assertEquals(1, locator.getRegionLocation(Bytes.toBytes("a")).getRegion().getRegionId());
101      assertEquals(2, locator.getRegionLocation(Bytes.toBytes("z")).getRegion().getRegionId());
102    }
103  }
104
105  private void writeManifest() throws IOException {
106    SnapshotDataManifest.Builder manifest = SnapshotDataManifest.newBuilder()
107      .setTableSchema(ProtobufUtil.toTableSchema(TABLE_DESCRIPTOR));
108    addRegion(manifest, 1, HConstants.EMPTY_START_ROW, SPLIT_KEY, false, false);
109    addRegion(manifest, 2, SPLIT_KEY, HConstants.EMPTY_END_ROW, false, false);
110    addRegion(manifest, 3, HConstants.EMPTY_START_ROW, SPLIT_KEY, true, false);
111    addRegion(manifest, 4, SPLIT_KEY, HConstants.EMPTY_END_ROW, false, true);
112
113    try (FSDataOutputStream out =
114      fs.create(new Path(snapshotDir, SnapshotManifest.DATA_MANIFEST_NAME))) {
115      manifest.build().writeTo(out);
116    }
117  }
118
119  private static void addRegion(SnapshotDataManifest.Builder manifest, long regionId,
120    byte[] startKey, byte[] endKey, boolean offline, boolean split) {
121    RegionInfo regionInfo = RegionInfoBuilder.newBuilder(TABLE_NAME).setRegionId(regionId)
122      .setStartKey(startKey).setEndKey(endKey).setOffline(offline).setSplit(split).build();
123    manifest.addRegionManifests(SnapshotRegionManifest.newBuilder()
124      .setRegionInfo(ProtobufUtil.toRegionInfo(regionInfo)).build());
125  }
126}