View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.regionserver;
20  
21  import static junit.framework.TestCase.assertNull;
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertFalse;
24  import static org.junit.Assert.assertNotNull;
25  import static org.junit.Assert.assertTrue;
26  import java.util.Collection;
27  
28  import org.apache.hadoop.hbase.HBaseTestingUtility;
29  import org.apache.hadoop.hbase.TableName;
30  import org.apache.hadoop.hbase.client.Delete;
31  import org.apache.hadoop.hbase.client.Get;
32  import org.apache.hadoop.hbase.client.HBaseAdmin;
33  import org.apache.hadoop.hbase.client.Put;
34  import org.apache.hadoop.hbase.client.Result;
35  import org.apache.hadoop.hbase.client.ResultScanner;
36  import org.apache.hadoop.hbase.client.Scan;
37  import org.apache.hadoop.hbase.client.Table;
38  import org.apache.hadoop.hbase.master.cleaner.TimeToLiveHFileCleaner;
39  import org.apache.hadoop.hbase.regionserver.compactions.CompactionConfiguration;
40  import org.apache.hadoop.hbase.testclassification.MediumTests;
41  import org.apache.hadoop.hbase.util.Bytes;
42  
43  import org.junit.AfterClass;
44  import org.junit.BeforeClass;
45  import org.junit.Test;
46  import org.junit.experimental.categories.Category;
47  
48  @Category({MediumTests.class})
49  public class TestCleanupCompactedFileOnRegionClose {
50  
51    private static HBaseTestingUtility util;
52  
53    @BeforeClass
54    public static void beforeClass() throws Exception {
55      util = new HBaseTestingUtility();
56      util.getConfiguration().setInt(CompactionConfiguration.HBASE_HSTORE_COMPACTION_MIN_KEY,100);
57      util.getConfiguration().set("dfs.blocksize", "64000");
58      util.getConfiguration().set("dfs.namenode.fs-limits.min-block-size", "1024");
59      util.getConfiguration().set(TimeToLiveHFileCleaner.TTL_CONF_KEY,"0");
60      util.startMiniCluster(2);
61    }
62  
63    @AfterClass
64    public static void afterclass() throws Exception {
65      util.shutdownMiniCluster();
66    }
67  
68    @Test
69    public void testCleanupOnClose() throws Exception {
70      TableName tableName = TableName.valueOf("testCleanupOnClose");
71      String familyName = "f";
72      byte[] familyNameBytes = Bytes.toBytes(familyName);
73      util.createTable(tableName, familyName);
74  
75      HBaseAdmin hBaseAdmin = util.getHBaseAdmin();
76      Table table = util.getConnection().getTable(tableName);
77  
78      HRegionServer rs = util.getRSForFirstRegionInTable(tableName);
79      Region region = rs.getOnlineRegions(tableName).get(0);
80  
81      int refSFCount = 4;
82      for (int i = 0; i < refSFCount; i++) {
83        for (int j = 0; j < refSFCount; j++) {
84          Put put = new Put(Bytes.toBytes(j));
85          put.addColumn(familyNameBytes, Bytes.toBytes(i), Bytes.toBytes(j));
86          table.put(put);
87        }
88        util.flush(tableName);
89      }
90      assertEquals(refSFCount, region.getStoreFileList(new byte[][]{familyNameBytes}).size());
91  
92      //add a delete, to test wether we end up with an inconsistency post region close
93      Delete delete = new Delete(Bytes.toBytes(refSFCount-1));
94      table.delete(delete);
95      util.flush(tableName);
96      assertFalse(table.exists(new Get(Bytes.toBytes(refSFCount-1))));
97  
98      //Create a scanner and keep it open to add references to StoreFileReaders
99      Scan scan = new Scan();
100     scan.setStopRow(Bytes.toBytes(refSFCount-2));
101     scan.setCaching(1);
102     ResultScanner scanner = table.getScanner(scan);
103     Result res = scanner.next();
104     assertNotNull(res);
105     assertEquals(refSFCount, res.getFamilyMap(familyNameBytes).size());
106 
107 
108     //Verify the references
109     int count = 0;
110     for (StoreFile sf : (Collection<StoreFile>)region.getStore(familyNameBytes).getStorefiles()) {
111       synchronized (sf) {
112         if (count < refSFCount) {
113           assertTrue(sf.getReader().isReferencedInReads());
114         } else {
115           assertFalse(sf.getReader().isReferencedInReads());
116         }
117       }
118       count++;
119     }
120 
121     //Major compact to produce compacted storefiles that need to be cleaned up
122     util.compact(tableName, true);
123     assertEquals(1, region.getStoreFileList(new byte[][]{familyNameBytes}).size());
124     assertEquals(refSFCount+1,
125       ((HStore)region.getStore(familyNameBytes)).getStoreEngine().getStoreFileManager()
126           .getCompactedfiles().size());
127 
128     //close then open the region to determine wether compacted storefiles get cleaned up on close
129     hBaseAdmin.unassign(region.getRegionInfo().getRegionName(), false);
130     hBaseAdmin.assign(region.getRegionInfo().getRegionName());
131     util.waitUntilNoRegionsInTransition(10000);
132 
133 
134     assertFalse("Deleted row should not exist",
135         table.exists(new Get(Bytes.toBytes(refSFCount-1))));
136 
137     rs = util.getRSForFirstRegionInTable(tableName);
138     region = rs.getOnlineRegions(tableName).get(0);
139     assertEquals(1, region.getStoreFileList(new byte[][]{familyNameBytes}).size());
140     assertNull(((HStore)region.getStore(familyNameBytes)).getStoreEngine().getStoreFileManager()
141         .getCompactedfiles());
142   }
143 }