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 org.apache.hadoop.conf.Configuration;
021import org.apache.hadoop.fs.FileStatus;
022import org.apache.hadoop.hbase.HBaseInterfaceAudience;
023import org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil;
024import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
025import org.apache.yetus.audience.InterfaceAudience;
026import org.slf4j.Logger;
027import org.slf4j.LoggerFactory;
028
029/**
030 * Procedure WAL cleaner that uses the timestamp of the Procedure WAL to determine if it should be
031 * deleted. By default they are allowed to live for {@value #DEFAULT_TTL}
032 */
033@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
034public class TimeToLiveProcedureWALCleaner extends BaseLogCleanerDelegate {
035  private static final Logger LOG =
036      LoggerFactory.getLogger(TimeToLiveProcedureWALCleaner.class.getName());
037  public static final String TTL_CONF_KEY = "hbase.master.procedurewalcleaner.ttl";
038  // default ttl = 7 days
039  public static final long DEFAULT_TTL = 604_800_000L;
040  // Configured time a procedure log can be kept after it was moved to the archive
041  private long ttl;
042  private boolean stopped = false;
043
044  @Override
045  public void setConf(Configuration conf) {
046    this.ttl = conf.getLong(TTL_CONF_KEY, DEFAULT_TTL);
047    super.setConf(conf);
048  }
049
050  @Override
051  public boolean isFileDeletable(FileStatus fStat) {
052    // Files are validated for the second time here,
053    // if it causes a bottleneck this logic needs refactored
054    if (!MasterProcedureUtil.validateProcedureWALFilename(fStat.getPath().getName())) {
055      return true;
056    }
057
058    long currentTime = EnvironmentEdgeManager.currentTime();
059    long time = fStat.getModificationTime();
060    long life = currentTime - time;
061    if (LOG.isTraceEnabled()) {
062      LOG.trace("Procedure log life:" + life + ", ttl:" + ttl + ", current:" + currentTime +
063          ", from: " + time);
064    }
065    if (life < 0) {
066      LOG.warn("Found a procedure log (" + fStat.getPath() + ") newer than current time ("
067          + currentTime + " < " + time + "), probably a clock skew");
068      return false;
069    }
070    return life > ttl;
071  }
072
073  @Override
074  public void stop(String why) {
075    this.stopped = true;
076  }
077
078  @Override
079  public boolean isStopped() {
080    return this.stopped;
081  }
082}