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