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