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}