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.regionserver; 019 020import java.io.IOException; 021import java.util.Random; 022import org.apache.hadoop.fs.FileSystem; 023import org.apache.hadoop.fs.Path; 024import org.apache.hadoop.hbase.HBaseClassTestRule; 025import org.apache.hadoop.hbase.HBaseTestingUtility; 026import org.apache.hadoop.hbase.HColumnDescriptor; 027import org.apache.hadoop.hbase.HTableDescriptor; 028import org.apache.hadoop.hbase.TableName; 029import org.apache.hadoop.hbase.client.Put; 030import org.apache.hadoop.hbase.client.Result; 031import org.apache.hadoop.hbase.client.ResultScanner; 032import org.apache.hadoop.hbase.client.Scan; 033import org.apache.hadoop.hbase.client.Table; 034import org.apache.hadoop.hbase.mob.MobConstants; 035import org.apache.hadoop.hbase.mob.MobUtils; 036import org.apache.hadoop.hbase.testclassification.MediumTests; 037import org.apache.hadoop.hbase.util.Bytes; 038import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 039import org.apache.hadoop.hbase.util.FSUtils; 040import org.apache.hadoop.hbase.util.HFileArchiveUtil; 041import org.junit.AfterClass; 042import org.junit.Assert; 043import org.junit.BeforeClass; 044import org.junit.ClassRule; 045import org.junit.Rule; 046import org.junit.Test; 047import org.junit.experimental.categories.Category; 048import org.junit.rules.TestName; 049 050@Category(MediumTests.class) 051public class TestDeleteMobTable { 052 053 @ClassRule 054 public static final HBaseClassTestRule CLASS_RULE = 055 HBaseClassTestRule.forClass(TestDeleteMobTable.class); 056 057 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 058 private final static byte[] FAMILY = Bytes.toBytes("family"); 059 private final static byte[] QF = Bytes.toBytes("qualifier"); 060 private static Random random = new Random(); 061 062 @Rule 063 public TestName name = new TestName(); 064 065 @BeforeClass 066 public static void setUpBeforeClass() throws Exception { 067 TEST_UTIL.startMiniCluster(1); 068 } 069 070 @AfterClass 071 public static void tearDownAfterClass() throws Exception { 072 TEST_UTIL.shutdownMiniCluster(); 073 } 074 075 /** 076 * Generate the mob value. 077 * 078 * @param size 079 * the size of the value 080 * @return the mob value generated 081 */ 082 private static byte[] generateMobValue(int size) { 083 byte[] mobVal = new byte[size]; 084 random.nextBytes(mobVal); 085 return mobVal; 086 } 087 088 private HTableDescriptor createTableDescriptor(TableName tableName, boolean hasMob) { 089 HTableDescriptor htd = new HTableDescriptor(tableName); 090 HColumnDescriptor hcd = new HColumnDescriptor(FAMILY); 091 if (hasMob) { 092 hcd.setMobEnabled(true); 093 hcd.setMobThreshold(0); 094 } 095 htd.addFamily(hcd); 096 return htd; 097 } 098 099 private Table createTableWithOneFile(HTableDescriptor htd) throws IOException { 100 Table table = TEST_UTIL.createTable(htd, null); 101 try { 102 // insert data 103 byte[] value = generateMobValue(10); 104 byte[] row = Bytes.toBytes("row"); 105 Put put = new Put(row); 106 put.addColumn(FAMILY, QF, EnvironmentEdgeManager.currentTime(), value); 107 table.put(put); 108 109 // create an hfile 110 TEST_UTIL.getAdmin().flush(htd.getTableName()); 111 } catch (IOException e) { 112 table.close(); 113 throw e; 114 } 115 return table; 116 } 117 118 @Test 119 public void testDeleteMobTable() throws Exception { 120 final TableName tableName = TableName.valueOf(name.getMethodName()); 121 HTableDescriptor htd = createTableDescriptor(tableName, true); 122 HColumnDescriptor hcd = htd.getFamily(FAMILY); 123 124 String fileName = null; 125 Table table = createTableWithOneFile(htd); 126 try { 127 // the mob file exists 128 Assert.assertEquals(1, countMobFiles(tableName, hcd.getNameAsString())); 129 Assert.assertEquals(0, countArchiveMobFiles(tableName, hcd.getNameAsString())); 130 fileName = assertHasOneMobRow(table, tableName, hcd.getNameAsString()); 131 Assert.assertFalse(mobArchiveExist(tableName, hcd.getNameAsString(), fileName)); 132 Assert.assertTrue(mobTableDirExist(tableName)); 133 } finally { 134 table.close(); 135 TEST_UTIL.deleteTable(tableName); 136 } 137 138 Assert.assertFalse(TEST_UTIL.getAdmin().tableExists(tableName)); 139 Assert.assertEquals(0, countMobFiles(tableName, hcd.getNameAsString())); 140 Assert.assertEquals(1, countArchiveMobFiles(tableName, hcd.getNameAsString())); 141 Assert.assertTrue(mobArchiveExist(tableName, hcd.getNameAsString(), fileName)); 142 Assert.assertFalse(mobTableDirExist(tableName)); 143 } 144 145 @Test 146 public void testDeleteNonMobTable() throws Exception { 147 final TableName tableName = TableName.valueOf(name.getMethodName()); 148 HTableDescriptor htd = createTableDescriptor(tableName, false); 149 HColumnDescriptor hcd = htd.getFamily(FAMILY); 150 151 Table table = createTableWithOneFile(htd); 152 try { 153 // the mob file doesn't exist 154 Assert.assertEquals(0, countMobFiles(tableName, hcd.getNameAsString())); 155 Assert.assertEquals(0, countArchiveMobFiles(tableName, hcd.getNameAsString())); 156 Assert.assertFalse(mobTableDirExist(tableName)); 157 } finally { 158 table.close(); 159 TEST_UTIL.deleteTable(tableName); 160 } 161 162 Assert.assertFalse(TEST_UTIL.getAdmin().tableExists(tableName)); 163 Assert.assertEquals(0, countMobFiles(tableName, hcd.getNameAsString())); 164 Assert.assertEquals(0, countArchiveMobFiles(tableName, hcd.getNameAsString())); 165 Assert.assertFalse(mobTableDirExist(tableName)); 166 } 167 168 @Test 169 public void testMobFamilyDelete() throws Exception { 170 final TableName tableName = TableName.valueOf(name.getMethodName()); 171 HTableDescriptor htd = createTableDescriptor(tableName, true); 172 HColumnDescriptor hcd = htd.getFamily(FAMILY); 173 htd.addFamily(new HColumnDescriptor(Bytes.toBytes("family2"))); 174 175 Table table = createTableWithOneFile(htd); 176 try { 177 // the mob file exists 178 Assert.assertEquals(1, countMobFiles(tableName, hcd.getNameAsString())); 179 Assert.assertEquals(0, countArchiveMobFiles(tableName, hcd.getNameAsString())); 180 String fileName = assertHasOneMobRow(table, tableName, hcd.getNameAsString()); 181 Assert.assertFalse(mobArchiveExist(tableName, hcd.getNameAsString(), fileName)); 182 Assert.assertTrue(mobTableDirExist(tableName)); 183 184 TEST_UTIL.getAdmin().deleteColumnFamily(tableName, FAMILY); 185 186 Assert.assertEquals(0, countMobFiles(tableName, hcd.getNameAsString())); 187 Assert.assertEquals(1, countArchiveMobFiles(tableName, hcd.getNameAsString())); 188 Assert.assertTrue(mobArchiveExist(tableName, hcd.getNameAsString(), fileName)); 189 Assert.assertFalse(mobColumnFamilyDirExist(tableName, hcd.getNameAsString())); 190 } finally { 191 table.close(); 192 TEST_UTIL.deleteTable(tableName); 193 } 194 } 195 196 private int countMobFiles(TableName tn, String familyName) throws IOException { 197 FileSystem fs = TEST_UTIL.getTestFileSystem(); 198 Path mobFileDir = MobUtils.getMobFamilyPath(TEST_UTIL.getConfiguration(), tn, familyName); 199 if (fs.exists(mobFileDir)) { 200 return fs.listStatus(mobFileDir).length; 201 } 202 return 0; 203 } 204 205 private int countArchiveMobFiles(TableName tn, String familyName) 206 throws IOException { 207 FileSystem fs = TEST_UTIL.getTestFileSystem(); 208 Path storePath = HFileArchiveUtil.getStoreArchivePath(TEST_UTIL.getConfiguration(), tn, 209 MobUtils.getMobRegionInfo(tn).getEncodedName(), familyName); 210 if (fs.exists(storePath)) { 211 return fs.listStatus(storePath).length; 212 } 213 return 0; 214 } 215 216 private boolean mobTableDirExist(TableName tn) throws IOException { 217 FileSystem fs = TEST_UTIL.getTestFileSystem(); 218 Path tableDir = FSUtils.getTableDir(MobUtils.getMobHome(TEST_UTIL.getConfiguration()), tn); 219 return fs.exists(tableDir); 220 } 221 222 private boolean mobColumnFamilyDirExist(TableName tn, String familyName) throws IOException { 223 FileSystem fs = TEST_UTIL.getTestFileSystem(); 224 Path mobFamilyDir = MobUtils.getMobFamilyPath(TEST_UTIL.getConfiguration(), tn, familyName); 225 return fs.exists(mobFamilyDir); 226 } 227 228 private boolean mobArchiveExist(TableName tn, String familyName, String fileName) 229 throws IOException { 230 FileSystem fs = TEST_UTIL.getTestFileSystem(); 231 Path storePath = HFileArchiveUtil.getStoreArchivePath(TEST_UTIL.getConfiguration(), tn, 232 MobUtils.getMobRegionInfo(tn).getEncodedName(), familyName); 233 return fs.exists(new Path(storePath, fileName)); 234 } 235 236 private String assertHasOneMobRow(Table table, TableName tn, String familyName) 237 throws IOException { 238 Scan scan = new Scan(); 239 scan.setAttribute(MobConstants.MOB_SCAN_RAW, Bytes.toBytes(Boolean.TRUE)); 240 ResultScanner rs = table.getScanner(scan); 241 Result r = rs.next(); 242 Assert.assertNotNull(r); 243 String fileName = MobUtils.getMobFileName(r.getColumnLatestCell(FAMILY, QF)); 244 Path filePath = new Path( 245 MobUtils.getMobFamilyPath(TEST_UTIL.getConfiguration(), tn, familyName), fileName); 246 FileSystem fs = TEST_UTIL.getTestFileSystem(); 247 Assert.assertTrue(fs.exists(filePath)); 248 r = rs.next(); 249 Assert.assertNull(r); 250 return fileName; 251 } 252}