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.mob; 019 020import java.io.IOException; 021import org.apache.hadoop.conf.Configuration; 022import org.apache.hadoop.conf.Configured; 023import org.apache.hadoop.fs.FileSystem; 024import org.apache.hadoop.hbase.HBaseConfiguration; 025import org.apache.hadoop.hbase.HConstants; 026import org.apache.hadoop.hbase.TableName; 027import org.apache.hadoop.hbase.client.Admin; 028import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; 029import org.apache.hadoop.hbase.client.Connection; 030import org.apache.hadoop.hbase.client.ConnectionFactory; 031import org.apache.hadoop.hbase.client.TableDescriptor; 032import org.apache.hadoop.hbase.io.hfile.CacheConfig; 033import org.apache.hadoop.hbase.util.Bytes; 034import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 035import org.apache.hadoop.util.Tool; 036import org.apache.hadoop.util.ToolRunner; 037import org.apache.yetus.audience.InterfaceAudience; 038import org.slf4j.Logger; 039import org.slf4j.LoggerFactory; 040 041/** 042 * The cleaner to delete the expired MOB files. 043 */ 044@InterfaceAudience.Private 045public class ExpiredMobFileCleaner extends Configured implements Tool { 046 047 private static final Logger LOG = LoggerFactory.getLogger(ExpiredMobFileCleaner.class); 048 049 /** 050 * Cleans the MOB files when they're expired and their min versions are 0. If the latest timestamp 051 * of Cells in a MOB file is older than the TTL in the column family, it's regarded as expired. 052 * This cleaner deletes them. At a time T0, the cells in a mob file M0 are expired. If a user 053 * starts a scan before T0, those mob cells are visible, this scan still runs after T0. At that 054 * time T1, this mob file M0 is expired, meanwhile a cleaner starts, the M0 is archived and can be 055 * read in the archive directory. 056 * @param tableName The current table name. 057 * @param family The current family. 058 */ 059 public void cleanExpiredMobFiles(TableDescriptor htd, ColumnFamilyDescriptor family) 060 throws IOException { 061 Configuration conf = getConf(); 062 String tableName = htd.getTableName().getNameAsString(); 063 FileSystem fs = FileSystem.get(conf); 064 LOG.info("Cleaning the expired MOB files of " + family.getNameAsString() + " in " + tableName); 065 // disable the block cache. 066 Configuration copyOfConf = new Configuration(conf); 067 copyOfConf.setFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 0f); 068 CacheConfig cacheConfig = new CacheConfig(copyOfConf); 069 MobUtils.cleanExpiredMobFiles(fs, conf, htd, family, cacheConfig, 070 EnvironmentEdgeManager.currentTime()); 071 } 072 073 public static void main(String[] args) throws Exception { 074 Configuration conf = HBaseConfiguration.create(); 075 ToolRunner.run(conf, new ExpiredMobFileCleaner(), args); 076 } 077 078 private void printUsage() { 079 System.err.println("Usage:\n" + "--------------------------\n" 080 + ExpiredMobFileCleaner.class.getName() + " tableName familyName"); 081 System.err.println(" tableName The table name"); 082 System.err.println(" familyName The column family name"); 083 } 084 085 @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "REC_CATCH_EXCEPTION", 086 justification = "Intentional") 087 @Override 088 public int run(String[] args) throws Exception { 089 if (args.length != 2) { 090 printUsage(); 091 return 1; 092 } 093 String tableName = args[0]; 094 String familyName = args[1]; 095 TableName tn = TableName.valueOf(tableName); 096 Connection connection = ConnectionFactory.createConnection(getConf()); 097 Admin admin = connection.getAdmin(); 098 try { 099 TableDescriptor htd = admin.getDescriptor(tn); 100 ColumnFamilyDescriptor family = htd.getColumnFamily(Bytes.toBytes(familyName)); 101 if (family == null || !family.isMobEnabled()) { 102 throw new IOException("Column family " + familyName + " is not a MOB column family"); 103 } 104 if (family.getMinVersions() > 0) { 105 throw new IOException( 106 "The minVersions of the column family is not 0, could not be handled by this cleaner"); 107 } 108 cleanExpiredMobFiles(htd, family); 109 return 0; 110 } finally { 111 admin.close(); 112 try { 113 connection.close(); 114 } catch (IOException e) { 115 LOG.error("Failed to close the connection.", e); 116 } 117 } 118 } 119}