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