View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.master.cleaner;
20  
21  import java.io.IOException;
22  import java.util.List;
23  import java.util.concurrent.TimeUnit;
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.hadoop.conf.Configuration;
27  import org.apache.hadoop.hbase.ScheduledChore;
28  import org.apache.hadoop.hbase.Stoppable;
29  import org.apache.hadoop.hbase.classification.InterfaceAudience;
30  import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
31  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
32  import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
33  
34  /**
35   * This chore, every time it runs, will try to delete snapshots that are expired based on TTL in
36   * seconds configured for each Snapshot
37   */
38  @InterfaceAudience.Private
39  public class SnapshotCleanerChore extends ScheduledChore {
40  
41    private static final Log LOG = LogFactory.getLog(SnapshotCleanerChore.class);
42    private static final String SNAPSHOT_CLEANER_CHORE_NAME = "SnapshotCleaner";
43    private static final String SNAPSHOT_CLEANER_INTERVAL = "hbase.master.cleaner.snapshot.interval";
44    private static final int SNAPSHOT_CLEANER_DEFAULT_INTERVAL = 1800 * 1000; // Default 30 min
45    private static final String DELETE_SNAPSHOT_EVENT =
46        "Eligible Snapshot for cleanup due to expired TTL.";
47  
48    private final SnapshotManager snapshotManager;
49  
50    /**
51     * Construct Snapshot Cleaner Chore with parameterized constructor
52     *
53     * @param stopper When {@link Stoppable#isStopped()} is true, this chore will cancel and cleanup
54     * @param configuration The configuration to set
55     * @param snapshotManager SnapshotManager instance to manage lifecycle of snapshot
56     */
57    public SnapshotCleanerChore(Stoppable stopper, Configuration configuration,
58            SnapshotManager snapshotManager) {
59      super(SNAPSHOT_CLEANER_CHORE_NAME, stopper, configuration.getInt(SNAPSHOT_CLEANER_INTERVAL,
60        SNAPSHOT_CLEANER_DEFAULT_INTERVAL));
61      this.snapshotManager = snapshotManager;
62    }
63  
64    @Override
65    protected void chore() {
66      if (LOG.isTraceEnabled()) {
67        LOG.trace("Snapshot Cleaner Chore is starting up...");
68      }
69      try {
70        List<SnapshotDescription> completedSnapshotsList =
71            this.snapshotManager.getCompletedSnapshots();
72        for (SnapshotDescription snapshotDescription : completedSnapshotsList) {
73          long snapshotCreatedTime = snapshotDescription.getCreationTime();
74          long snapshotTtl = snapshotDescription.getTtl();
75          /*
76           * Backward compatibility after the patch deployment on HMaster
77           * Any snapshot with ttl 0 is to be considered as snapshot to keep FOREVER
78           * Default ttl value specified by {@HConstants.DEFAULT_SNAPSHOT_TTL}
79           */
80          if (snapshotCreatedTime > 0 && snapshotTtl > 0 &&
81              snapshotTtl < TimeUnit.MILLISECONDS.toSeconds(Long.MAX_VALUE)) {
82            long currentTime = EnvironmentEdgeManager.currentTime();
83            if ((snapshotCreatedTime + TimeUnit.SECONDS.toMillis(snapshotTtl)) < currentTime) {
84              LOG.info("Event: " + DELETE_SNAPSHOT_EVENT + " Name: " + snapshotDescription.getName() +
85                ", CreatedTime: " + snapshotCreatedTime + ", TTL: " + snapshotTtl +
86                ", currentTime: " + currentTime);
87              deleteExpiredSnapshot(snapshotDescription);
88            }
89          }
90        }
91      } catch (IOException e) {
92        LOG.error("Error while cleaning up Snapshots...", e);
93      }
94      if (LOG.isTraceEnabled()) {
95        LOG.trace("Snapshot Cleaner Chore is closing...");
96      }
97    }
98  
99    private void deleteExpiredSnapshot(SnapshotDescription snapshotDescription) {
100     try {
101       this.snapshotManager.deleteSnapshot(snapshotDescription);
102     } catch (Exception e) {
103       LOG.error("Error while deleting Snapshot: " + snapshotDescription.getName(), e);
104     }
105   }
106 
107 }