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.HBaseTestingUtil;
025import org.apache.hadoop.hbase.TableName;
026import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
027import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
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.client.TableDescriptor;
034import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
035import org.apache.hadoop.hbase.mob.MobConstants;
036import org.apache.hadoop.hbase.mob.MobUtils;
037import org.apache.hadoop.hbase.testclassification.MediumTests;
038import org.apache.hadoop.hbase.util.Bytes;
039import org.apache.hadoop.hbase.util.CommonFSUtils;
040import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
041import org.apache.hadoop.hbase.util.HFileArchiveUtil;
042import org.junit.AfterClass;
043import org.junit.Assert;
044import org.junit.BeforeClass;
045import org.junit.ClassRule;
046import org.junit.Rule;
047import org.junit.Test;
048import org.junit.experimental.categories.Category;
049import org.junit.rules.TestName;
050
051@Category(MediumTests.class)
052public class TestDeleteMobTable {
053
054  @ClassRule
055  public static final HBaseClassTestRule CLASS_RULE =
056    HBaseClassTestRule.forClass(TestDeleteMobTable.class);
057
058  private final static HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
059  private final static byte[] FAMILY = Bytes.toBytes("family");
060  private final static byte[] QF = Bytes.toBytes("qualifier");
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. the size of the value
077   * @return the mob value generated
078   */
079  private static byte[] generateMobValue(int size) {
080    byte[] mobVal = new byte[size];
081    Bytes.random(mobVal);
082    return mobVal;
083  }
084
085  private TableDescriptor createTableDescriptor(TableName tableName, boolean hasMob) {
086    ColumnFamilyDescriptorBuilder builder = ColumnFamilyDescriptorBuilder.newBuilder(FAMILY);
087    if (hasMob) {
088      builder.setMobEnabled(true);
089      builder.setMobThreshold(0);
090    }
091    return TableDescriptorBuilder.newBuilder(tableName).setColumnFamily(builder.build()).build();
092  }
093
094  private Table createTableWithOneFile(TableDescriptor tableDescriptor) throws IOException {
095    Table table = TEST_UTIL.createTable(tableDescriptor, 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(tableDescriptor.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    TableDescriptor tableDescriptor = createTableDescriptor(tableName, true);
117    ColumnFamilyDescriptor familyDescriptor = tableDescriptor.getColumnFamily(FAMILY);
118
119    String fileName = null;
120    Table table = createTableWithOneFile(tableDescriptor);
121    try {
122      // the mob file exists
123      Assert.assertEquals(1, countMobFiles(tableName, familyDescriptor.getNameAsString()));
124      Assert.assertEquals(0, countArchiveMobFiles(tableName, familyDescriptor.getNameAsString()));
125      fileName = assertHasOneMobRow(table, tableName, familyDescriptor.getNameAsString());
126      Assert.assertFalse(mobArchiveExist(tableName, familyDescriptor.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, familyDescriptor.getNameAsString()));
135    Assert.assertEquals(1, countArchiveMobFiles(tableName, familyDescriptor.getNameAsString()));
136    Assert.assertTrue(mobArchiveExist(tableName, familyDescriptor.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    TableDescriptor htd = createTableDescriptor(tableName, false);
144    ColumnFamilyDescriptor hcd = htd.getColumnFamily(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    TableDescriptor tableDescriptor = createTableDescriptor(tableName, true);
167    ColumnFamilyDescriptor familyDescriptor = tableDescriptor.getColumnFamily(FAMILY);
168    tableDescriptor = TableDescriptorBuilder.newBuilder(tableDescriptor)
169      .setColumnFamily(ColumnFamilyDescriptorBuilder.of(Bytes.toBytes("family2"))).build();
170
171    Table table = createTableWithOneFile(tableDescriptor);
172    try {
173      // the mob file exists
174      Assert.assertEquals(1, countMobFiles(tableName, familyDescriptor.getNameAsString()));
175      Assert.assertEquals(0, countArchiveMobFiles(tableName, familyDescriptor.getNameAsString()));
176      String fileName = assertHasOneMobRow(table, tableName, familyDescriptor.getNameAsString());
177      Assert.assertFalse(mobArchiveExist(tableName, familyDescriptor.getNameAsString(), fileName));
178      Assert.assertTrue(mobTableDirExist(tableName));
179
180      TEST_UTIL.getAdmin().deleteColumnFamily(tableName, FAMILY);
181
182      Assert.assertEquals(0, countMobFiles(tableName, familyDescriptor.getNameAsString()));
183      Assert.assertEquals(1, countArchiveMobFiles(tableName, familyDescriptor.getNameAsString()));
184      Assert.assertTrue(mobArchiveExist(tableName, familyDescriptor.getNameAsString(), fileName));
185      Assert.assertFalse(mobColumnFamilyDirExist(tableName, familyDescriptor.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) throws IOException {
202    FileSystem fs = TEST_UTIL.getTestFileSystem();
203    Path storePath = HFileArchiveUtil.getStoreArchivePath(TEST_UTIL.getConfiguration(), tn,
204      MobUtils.getMobRegionInfo(tn).getEncodedName(), familyName);
205    if (fs.exists(storePath)) {
206      return fs.listStatus(storePath).length;
207    }
208    return 0;
209  }
210
211  private boolean mobTableDirExist(TableName tn) throws IOException {
212    FileSystem fs = TEST_UTIL.getTestFileSystem();
213    Path tableDir =
214      CommonFSUtils.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 =
241      new Path(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}