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.master.region;
019
020import static org.junit.jupiter.api.Assertions.assertArrayEquals;
021import static org.junit.jupiter.api.Assertions.assertEquals;
022import static org.junit.jupiter.api.Assertions.assertFalse;
023import static org.junit.jupiter.api.Assertions.assertNull;
024import static org.junit.jupiter.api.Assertions.assertTrue;
025
026import java.io.IOException;
027import org.apache.hadoop.conf.Configuration;
028import org.apache.hadoop.fs.Path;
029import org.apache.hadoop.hbase.HBaseConfiguration;
030import org.apache.hadoop.hbase.HConstants;
031import org.apache.hadoop.hbase.client.Get;
032import org.apache.hadoop.hbase.client.Put;
033import org.apache.hadoop.hbase.client.TableDescriptor;
034import org.apache.hadoop.hbase.regionserver.HRegion.FlushResult;
035import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
036import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTrackerFactory;
037import org.apache.hadoop.hbase.testclassification.MasterTests;
038import org.apache.hadoop.hbase.testclassification.MediumTests;
039import org.apache.hadoop.hbase.util.Bytes;
040import org.apache.hadoop.hbase.util.CommonFSUtils;
041import org.apache.hadoop.hbase.util.FSTableDescriptors;
042import org.junit.jupiter.api.Tag;
043import org.junit.jupiter.api.Test;
044
045@Tag(MasterTests.TAG)
046@Tag(MediumTests.TAG)
047public class TestMasterRegionInitialize extends MasterRegionTestBase {
048
049  @Test
050  public void testUpgrade() throws IOException {
051    Path rootDir = new Path(htu.getDataTestDir(), REGION_DIR_NAME);
052    Path tableDir =
053      CommonFSUtils.getTableDir(rootDir, region.region.getTableDescriptor().getTableName());
054    Path initializingFlag = new Path(tableDir, MasterRegion.INITIALIZING_FLAG);
055    Path initializedFlag = new Path(tableDir, MasterRegion.INITIALIZED_FLAG);
056    HRegionFileSystem hfs = region.region.getRegionFileSystem();
057    assertFalse(hfs.getFileSystem().exists(initializingFlag));
058    assertTrue(hfs.getFileSystem().exists(initializedFlag));
059    byte[] row = Bytes.toBytes("row");
060    byte[] cf = CF1;
061    byte[] cq = Bytes.toBytes("qual");
062    byte[] value = Bytes.toBytes("value");
063    region.update(r -> r.put(new Put(row).addColumn(cf, cq, value)));
064    assertEquals(FlushResult.Result.FLUSHED_NO_COMPACTION_NEEDED, region.flush(true).getResult());
065    // delete initialized flag to simulate old implementation
066    hfs.getFileSystem().delete(initializedFlag, true);
067    FSTableDescriptors.deleteTableDescriptors(hfs.getFileSystem(), tableDir);
068    assertNull(FSTableDescriptors.getTableDescriptorFromFs(hfs.getFileSystem(), tableDir));
069    // reopen, with new file tracker
070    region.close(false);
071    htu.getConfiguration().set(StoreFileTrackerFactory.TRACKER_IMPL,
072      StoreFileTrackerFactory.Trackers.FILE.name());
073    createMasterRegion();
074
075    // make sure we successfully upgrade to new implementation without data loss
076    hfs = region.region.getRegionFileSystem();
077    assertFalse(hfs.getFileSystem().exists(initializingFlag));
078    assertTrue(hfs.getFileSystem().exists(initializedFlag));
079    TableDescriptor td = FSTableDescriptors.getTableDescriptorFromFs(hfs.getFileSystem(), tableDir);
080    assertEquals(StoreFileTrackerFactory.Trackers.FILE.name(),
081      td.getValue(StoreFileTrackerFactory.TRACKER_IMPL));
082    assertArrayEquals(value, region.get(new Get(row)).getValue(cf, cq));
083  }
084
085  @Test
086  public void testInitializingCleanup() throws IOException {
087    Path rootDir = new Path(htu.getDataTestDir(), REGION_DIR_NAME);
088    Path tableDir =
089      CommonFSUtils.getTableDir(rootDir, region.region.getTableDescriptor().getTableName());
090    Path initializingFlag = new Path(tableDir, MasterRegion.INITIALIZING_FLAG);
091    Path initializedFlag = new Path(tableDir, MasterRegion.INITIALIZED_FLAG);
092    HRegionFileSystem hfs = region.region.getRegionFileSystem();
093    assertFalse(hfs.getFileSystem().exists(initializingFlag));
094    assertTrue(hfs.getFileSystem().exists(initializedFlag));
095    byte[] row = Bytes.toBytes("row");
096    byte[] cf = CF1;
097    byte[] cq = Bytes.toBytes("qual");
098    byte[] value = Bytes.toBytes("value");
099    region.update(r -> r.put(new Put(row).addColumn(cf, cq, value)));
100    // delete initialized flag and touch a initializing flag, to simulate initializing in progress
101    hfs.getFileSystem().delete(initializedFlag, true);
102    if (!hfs.getFileSystem().mkdirs(initializingFlag)) {
103      throw new IOException("can not touch " + initializedFlag);
104    }
105
106    region.close(false);
107    createMasterRegion();
108    hfs = region.region.getRegionFileSystem();
109    assertFalse(hfs.getFileSystem().exists(initializingFlag));
110    assertTrue(hfs.getFileSystem().exists(initializedFlag));
111
112    // but the data should have been cleaned up
113    assertTrue(region.get(new Get(row)).isEmpty());
114  }
115
116  @Test
117  public void testMasterRegionDirSuffix() {
118    String currentMasterRegionDirName = MasterRegionFactory.getMasterRegionDirName();
119    assertEquals("MasterData", currentMasterRegionDirName,
120      "Default master region directory should be MasterData");
121
122    Configuration confWithSuffix = HBaseConfiguration.create();
123    String suffix = "replica1";
124    confWithSuffix.set(HConstants.HBASE_META_TABLE_SUFFIX, suffix);
125    String dirNameWithSuffix = MasterRegionFactory.initMasterRegionDirName(confWithSuffix);
126    String expectedDirName = "MasterData_" + suffix;
127    assertEquals(expectedDirName, dirNameWithSuffix,
128      "Directory name should have suffix when configured");
129  }
130}