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