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