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.master.cleaner; 019 020import java.io.IOException; 021import java.util.List; 022import java.util.concurrent.TimeUnit; 023import org.apache.hadoop.conf.Configuration; 024import org.apache.hadoop.hbase.ScheduledChore; 025import org.apache.hadoop.hbase.Stoppable; 026import org.apache.hadoop.hbase.master.snapshot.SnapshotManager; 027import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 028import org.apache.yetus.audience.InterfaceAudience; 029import org.slf4j.Logger; 030import org.slf4j.LoggerFactory; 031 032import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos; 033 034/** 035 * This chore, every time it runs, will try to delete snapshots that are expired based on TTL in 036 * seconds configured for each Snapshot 037 */ 038@InterfaceAudience.Private 039public class SnapshotCleanerChore extends ScheduledChore { 040 041 private static final Logger LOG = LoggerFactory.getLogger(SnapshotCleanerChore.class); 042 private static final String SNAPSHOT_CLEANER_CHORE_NAME = "SnapshotCleaner"; 043 private static final String SNAPSHOT_CLEANER_INTERVAL = "hbase.master.cleaner.snapshot.interval"; 044 private static final int SNAPSHOT_CLEANER_DEFAULT_INTERVAL = 1800 * 1000; // Default 30 min 045 private static final String DELETE_SNAPSHOT_EVENT = 046 "Eligible Snapshot for cleanup due to expired TTL."; 047 048 private final SnapshotManager snapshotManager; 049 050 /** 051 * Construct Snapshot Cleaner Chore with parameterized constructor 052 * @param stopper When {@link Stoppable#isStopped()} is true, this chore will cancel and 053 * cleanup 054 * @param configuration The configuration to set 055 * @param snapshotManager SnapshotManager instance to manage lifecycle of snapshot 056 */ 057 public SnapshotCleanerChore(Stoppable stopper, Configuration configuration, 058 SnapshotManager snapshotManager) { 059 super(SNAPSHOT_CLEANER_CHORE_NAME, stopper, 060 configuration.getInt(SNAPSHOT_CLEANER_INTERVAL, SNAPSHOT_CLEANER_DEFAULT_INTERVAL)); 061 this.snapshotManager = snapshotManager; 062 } 063 064 @Override 065 protected void chore() { 066 if (LOG.isTraceEnabled()) { 067 LOG.trace("Snapshot Cleaner Chore is starting up..."); 068 } 069 try { 070 List<SnapshotProtos.SnapshotDescription> completedSnapshotsList = 071 this.snapshotManager.getCompletedSnapshots(); 072 for (SnapshotProtos.SnapshotDescription snapshotDescription : completedSnapshotsList) { 073 long snapshotCreatedTime = snapshotDescription.getCreationTime(); 074 long snapshotTtl = snapshotDescription.getTtl(); 075 /* 076 * Backward compatibility after the patch deployment on HMaster Any snapshot with ttl 0 is 077 * to be considered as snapshot to keep FOREVER Default ttl value specified by 078 * {@HConstants.DEFAULT_SNAPSHOT_TTL} 079 */ 080 if ( 081 snapshotCreatedTime > 0 && snapshotTtl > 0 082 && snapshotTtl < TimeUnit.MILLISECONDS.toSeconds(Long.MAX_VALUE) 083 ) { 084 long currentTime = EnvironmentEdgeManager.currentTime(); 085 if ((snapshotCreatedTime + TimeUnit.SECONDS.toMillis(snapshotTtl)) < currentTime) { 086 LOG.info("Event: {} Name: {}, CreatedTime: {}, TTL: {}, currentTime: {}", 087 DELETE_SNAPSHOT_EVENT, snapshotDescription.getName(), snapshotCreatedTime, 088 snapshotTtl, currentTime); 089 deleteExpiredSnapshot(snapshotDescription); 090 } 091 } 092 } 093 } catch (IOException e) { 094 LOG.error("Error while cleaning up Snapshots...", e); 095 } 096 if (LOG.isTraceEnabled()) { 097 LOG.trace("Snapshot Cleaner Chore is closing..."); 098 } 099 } 100 101 private void deleteExpiredSnapshot(SnapshotProtos.SnapshotDescription snapshotDescription) { 102 try { 103 this.snapshotManager.deleteSnapshot(snapshotDescription); 104 } catch (Exception e) { 105 LOG.error("Error while deleting Snapshot: {}", snapshotDescription.getName(), e); 106 } 107 } 108 109}