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.util.compaction;
019
020import static org.junit.jupiter.api.Assertions.assertEquals;
021import static org.junit.jupiter.api.Assertions.assertTrue;
022
023import java.io.IOException;
024import org.apache.hadoop.hbase.HBaseTestingUtil;
025import org.apache.hadoop.hbase.TableName;
026import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
027import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
028import org.apache.hadoop.hbase.client.Connection;
029import org.apache.hadoop.hbase.client.Table;
030import org.apache.hadoop.hbase.client.TableDescriptor;
031import org.apache.hadoop.hbase.testclassification.MediumTests;
032import org.apache.hadoop.hbase.testclassification.MiscTests;
033import org.junit.jupiter.api.AfterEach;
034import org.junit.jupiter.api.BeforeEach;
035import org.junit.jupiter.api.Tag;
036import org.junit.jupiter.api.Test;
037import org.junit.jupiter.api.TestInfo;
038
039@Tag(MiscTests.TAG)
040@Tag(MediumTests.TAG)
041public class TestMajorCompactorTTL extends TestMajorCompactor {
042
043  @BeforeEach
044  @Override
045  public void setUp() throws Exception {
046    utility = new HBaseTestingUtil();
047    utility.getConfiguration().setInt("hbase.hfile.compaction.discharger.interval", 10);
048    utility.startMiniCluster();
049    admin = utility.getAdmin();
050  }
051
052  @AfterEach
053  @Override
054  public void tearDown() throws Exception {
055    utility.shutdownMiniCluster();
056  }
057
058  @Test
059  public void testCompactingATable(TestInfo testInfo) throws Exception {
060    TableName tableName = createTable(testInfo.getTestMethod().get().getName());
061
062    // Delay a bit, so we can set the table TTL to 5 seconds
063    Thread.sleep(10 * 1000);
064
065    int numberOfRegions = admin.getRegions(tableName).size();
066    int numHFiles = utility.getNumHFiles(tableName, FAMILY);
067    // we should have a table with more store files than we would before we major compacted.
068    assertTrue(numberOfRegions < numHFiles);
069    modifyTTL(tableName);
070
071    MajorCompactorTTL compactor =
072      new MajorCompactorTTL(utility.getConfiguration(), admin.getDescriptor(tableName), 1, 200);
073    compactor.initializeWorkQueues();
074    compactor.compactAllRegions();
075    compactor.shutdown();
076
077    // verify that the store has been completely major compacted.
078    numberOfRegions = admin.getRegions(tableName).size();
079    numHFiles = utility.getNumHFiles(tableName, FAMILY);
080    assertEquals(numberOfRegions, numHFiles);
081  }
082
083  protected void modifyTTL(TableName tableName) throws IOException, InterruptedException {
084    // Set the TTL to 5 secs, so all the files just written above will get cleaned up on compact.
085    admin.disableTable(tableName);
086    utility.waitTableDisabled(tableName.getName());
087    TableDescriptor descriptor = admin.getDescriptor(tableName);
088    ColumnFamilyDescriptor colDesc = descriptor.getColumnFamily(FAMILY);
089    ColumnFamilyDescriptorBuilder cFDB = ColumnFamilyDescriptorBuilder.newBuilder(colDesc);
090    cFDB.setTimeToLive(5);
091    admin.modifyColumnFamily(tableName, cFDB.build());
092    admin.enableTable(tableName);
093    utility.waitTableEnabled(tableName);
094  }
095
096  protected TableName createTable(String name) throws IOException, InterruptedException {
097    TableName tableName = TableName.valueOf(name);
098    utility.createMultiRegionTable(tableName, FAMILY, 5);
099    utility.waitTableAvailable(tableName);
100    Connection connection = utility.getConnection();
101    Table table = connection.getTable(tableName);
102    // write data and flush multiple store files:
103    for (int i = 0; i < 5; i++) {
104      utility.loadRandomRows(table, FAMILY, 50, 100);
105      utility.flush(tableName);
106    }
107    table.close();
108    return tableName;
109  }
110}