HBASE-12015 Not cleaning Mob data when Mob CF is removed from table.(Pankaj Kumar)

This commit is contained in:
anoopsjohn 2015-07-13 14:36:44 +05:30
parent a1060d1390
commit d1f7bcbff7
8 changed files with 105 additions and 10 deletions

View File

@ -46,9 +46,10 @@ import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.TableDescriptor; import org.apache.hadoop.hbase.TableDescriptor;
import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.backup.HFileArchiver; import org.apache.hadoop.hbase.backup.HFileArchiver;
import org.apache.hadoop.hbase.client.TableState;
import org.apache.hadoop.hbase.exceptions.DeserializationException; import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.fs.HFileSystem; import org.apache.hadoop.hbase.fs.HFileSystem;
import org.apache.hadoop.hbase.mob.MobConstants;
import org.apache.hadoop.hbase.mob.MobUtils;
import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos.SplitLogTask.RecoveryMode; import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos.SplitLogTask.RecoveryMode;
import org.apache.hadoop.hbase.regionserver.HRegion; import org.apache.hadoop.hbase.regionserver.HRegion;
import org.apache.hadoop.hbase.wal.DefaultWALProvider; import org.apache.hadoop.hbase.wal.DefaultWALProvider;
@ -573,7 +574,7 @@ public class MasterFileSystem {
// @see HRegion.checkRegioninfoOnFilesystem() // @see HRegion.checkRegioninfoOnFilesystem()
} }
public void deleteFamilyFromFS(HRegionInfo region, byte[] familyName) public void deleteFamilyFromFS(HRegionInfo region, byte[] familyName, boolean hasMob)
throws IOException { throws IOException {
// archive family store files // archive family store files
Path tableDir = FSUtils.getTableDir(rootdir, region.getTable()); Path tableDir = FSUtils.getTableDir(rootdir, region.getTable());
@ -590,6 +591,22 @@ public class MasterFileSystem {
+ ")"); + ")");
} }
} }
// archive and delete mob files
if (hasMob) {
Path mobTableDir =
FSUtils.getTableDir(new Path(getRootDir(), MobConstants.MOB_DIR_NAME), region.getTable());
HRegionInfo mobRegionInfo = MobUtils.getMobRegionInfo(region.getTable());
Path mobFamilyDir =
new Path(mobTableDir,
new Path(mobRegionInfo.getEncodedName(), Bytes.toString(familyName)));
// archive mob family store files
MobUtils.archiveMobStoreFiles(conf, fs, mobRegionInfo, mobFamilyDir, familyName);
if (!fs.delete(mobFamilyDir, true)) {
throw new IOException("Could not delete mob store files for family "
+ Bytes.toString(familyName) + " from FileSystem region "
+ mobRegionInfo.getRegionNameAsString() + "(" + mobRegionInfo.getEncodedName() + ")");
}
}
} }
public void stop() { public void stop() {

View File

@ -312,7 +312,7 @@ public class AddColumnFamilyProcedure
// Remove the column family from file system and update the table descriptor to // Remove the column family from file system and update the table descriptor to
// the before-add-column-family-state // the before-add-column-family-state
MasterDDLOperationHelper.deleteColumnFamilyFromFileSystem(env, tableName, MasterDDLOperationHelper.deleteColumnFamilyFromFileSystem(env, tableName,
getRegionInfoList(env), cfDescriptor.getName()); getRegionInfoList(env), cfDescriptor.getName(), cfDescriptor.isMobEnabled());
env.getMasterServices().getTableDescriptors().add(unmodifiedHTableDescriptor); env.getMasterServices().getTableDescriptors().add(unmodifiedHTableDescriptor);

View File

@ -57,6 +57,7 @@ public class DeleteColumnFamilyProcedure
private HTableDescriptor unmodifiedHTableDescriptor; private HTableDescriptor unmodifiedHTableDescriptor;
private TableName tableName; private TableName tableName;
private byte [] familyName; private byte [] familyName;
private boolean hasMob;
private UserGroupInformation user; private UserGroupInformation user;
private List<HRegionInfo> regionInfoList; private List<HRegionInfo> regionInfoList;
@ -283,6 +284,8 @@ public class DeleteColumnFamilyProcedure
throw new InvalidFamilyOperationException("Family '" + getColumnFamilyName() throw new InvalidFamilyOperationException("Family '" + getColumnFamilyName()
+ "' does not exist, so it cannot be deleted"); + "' does not exist, so it cannot be deleted");
} }
// whether mob family
hasMob = unmodifiedHTableDescriptor.getFamily(familyName).isMobEnabled();
} }
/** /**
@ -334,7 +337,7 @@ public class DeleteColumnFamilyProcedure
**/ **/
private void deleteFromFs(final MasterProcedureEnv env) throws IOException { private void deleteFromFs(final MasterProcedureEnv env) throws IOException {
MasterDDLOperationHelper.deleteColumnFamilyFromFileSystem(env, tableName, MasterDDLOperationHelper.deleteColumnFamilyFromFileSystem(env, tableName,
getRegionInfoList(env), familyName); getRegionInfoList(env), familyName, hasMob);
} }
/** /**

View File

@ -91,7 +91,8 @@ public final class MasterDDLOperationHelper {
final MasterProcedureEnv env, final MasterProcedureEnv env,
final TableName tableName, final TableName tableName,
List<HRegionInfo> regionInfoList, List<HRegionInfo> regionInfoList,
final byte[] familyName) throws IOException { final byte[] familyName,
boolean hasMob) throws IOException {
final MasterFileSystem mfs = env.getMasterServices().getMasterFileSystem(); final MasterFileSystem mfs = env.getMasterServices().getMasterFileSystem();
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("Removing family=" + Bytes.toString(familyName) + " from table=" + tableName); LOG.debug("Removing family=" + Bytes.toString(familyName) + " from table=" + tableName);
@ -101,7 +102,7 @@ public final class MasterDDLOperationHelper {
} }
for (HRegionInfo hri : regionInfoList) { for (HRegionInfo hri : regionInfoList) {
// Delete the family directory in FS for all the regions one by one // Delete the family directory in FS for all the regions one by one
mfs.deleteFamilyFromFS(hri, familyName); mfs.deleteFamilyFromFS(hri, familyName, hasMob);
} }
} }

View File

@ -368,7 +368,8 @@ public class ModifyTableProcedure
env, env,
getTableName(), getTableName(),
getRegionInfoList(env), getRegionInfoList(env),
familyName); familyName,
oldHTableDescriptor.getFamily(familyName).isMobEnabled());
} }
} }
} }

View File

@ -45,6 +45,7 @@ import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellComparator; import org.apache.hadoop.hbase.CellComparator;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.HRegionInfo;
@ -870,4 +871,27 @@ public class MobUtils {
return false; return false;
} }
} }
/**
* Archive mob store files
* @param conf The current configuration.
* @param fs The current file system.
* @param mobRegionInfo The mob family region info.
* @param mobFamilyDir The mob family directory.
* @param family The name of the column family.
* @throws IOException
*/
public static void archiveMobStoreFiles(Configuration conf, FileSystem fs,
HRegionInfo mobRegionInfo, Path mobFamilyDir, byte[] family) throws IOException {
// disable the block cache.
Configuration copyOfConf = HBaseConfiguration.create(conf);
copyOfConf.setFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 0f);
CacheConfig cacheConfig = new CacheConfig(copyOfConf);
FileStatus[] fileStatus = FSUtils.listStatus(fs, mobFamilyDir);
List<StoreFile> storeFileList = new ArrayList<StoreFile>();
for (FileStatus file : fileStatus) {
storeFileList.add(new StoreFile(fs, file.getPath(), conf, cacheConfig, BloomType.NONE));
}
HFileArchiver.archiveStoreFiles(conf, fs, mobRegionInfo, mobFamilyDir, family, storeFileList);
}
} }

View File

@ -64,10 +64,8 @@ public class HFileArchiveUtil {
HRegionInfo region, HRegionInfo region,
Path tabledir, Path tabledir,
byte[] family) throws IOException { byte[] family) throws IOException {
TableName tableName =
FSUtils.getTableName(tabledir);
Path rootDir = FSUtils.getRootDir(conf); Path rootDir = FSUtils.getRootDir(conf);
Path tableArchiveDir = getTableArchivePath(rootDir, tableName); Path tableArchiveDir = getTableArchivePath(rootDir, region.getTable());
return HStore.getStoreHomedir(tableArchiveDir, region, family); return HStore.getStoreHomedir(tableArchiveDir, region, family);
} }

View File

@ -24,6 +24,7 @@ import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*; import org.apache.hadoop.hbase.client.*;
@ -161,6 +162,48 @@ public class TestDeleteMobTable {
} }
} }
} }
@Test
public void testMobFamilyDelete() throws Exception {
byte[] tableName = Bytes.toBytes("testMobFamilyDelete");
TableName tn = TableName.valueOf(tableName);
HTableDescriptor htd = new HTableDescriptor(tn);
HColumnDescriptor hcd = new HColumnDescriptor(FAMILY);
hcd.setMobEnabled(true);
hcd.setMobThreshold(0);
htd.addFamily(hcd);
htd.addFamily(new HColumnDescriptor(Bytes.toBytes("family2")));
HBaseAdmin admin = null;
Table table = null;
try {
admin = TEST_UTIL.getHBaseAdmin();
admin.createTable(htd);
table = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration()).getTable(tn);
byte[] value = generateMobValue(10);
byte[] row = Bytes.toBytes("row");
Put put = new Put(row);
put.addColumn(FAMILY, QF, EnvironmentEdgeManager.currentTime(), value);
table.put(put);
admin.flush(tn);
// the mob file exists
Assert.assertEquals(1, countMobFiles(tn, hcd.getNameAsString()));
Assert.assertEquals(0, countArchiveMobFiles(tn, hcd.getNameAsString()));
String fileName = assertHasOneMobRow(table, tn, hcd.getNameAsString());
Assert.assertFalse(mobArchiveExist(tn, hcd.getNameAsString(), fileName));
Assert.assertTrue(mobTableDirExist(tn));
admin.deleteColumnFamily(tn, FAMILY);
Assert.assertEquals(0, countMobFiles(tn, hcd.getNameAsString()));
Assert.assertEquals(1, countArchiveMobFiles(tn, hcd.getNameAsString()));
Assert.assertTrue(mobArchiveExist(tn, hcd.getNameAsString(), fileName));
Assert.assertFalse(mobColumnFamilyDirExist(tn));
} finally {
table.close();
if (admin != null) {
admin.close();
}
TEST_UTIL.deleteTable(tableName);
}
}
private int countMobFiles(TableName tn, String familyName) throws IOException { private int countMobFiles(TableName tn, String familyName) throws IOException {
FileSystem fs = TEST_UTIL.getTestFileSystem(); FileSystem fs = TEST_UTIL.getTestFileSystem();
@ -189,6 +232,14 @@ public class TestDeleteMobTable {
Path tableDir = FSUtils.getTableDir(MobUtils.getMobHome(TEST_UTIL.getConfiguration()), tn); Path tableDir = FSUtils.getTableDir(MobUtils.getMobHome(TEST_UTIL.getConfiguration()), tn);
return fs.exists(tableDir); return fs.exists(tableDir);
} }
private boolean mobColumnFamilyDirExist(TableName tn) throws IOException {
FileSystem fs = TEST_UTIL.getTestFileSystem();
Path tableDir = FSUtils.getTableDir(MobUtils.getMobHome(TEST_UTIL.getConfiguration()), tn);
HRegionInfo mobRegionInfo = MobUtils.getMobRegionInfo(tn);
Path mobFamilyDir = new Path(tableDir, new Path(mobRegionInfo.getEncodedName(), Bytes.toString(FAMILY)));
return fs.exists(mobFamilyDir);
}
private boolean mobArchiveExist(TableName tn, String familyName, String fileName) private boolean mobArchiveExist(TableName tn, String familyName, String fileName)
throws IOException { throws IOException {