/**
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.hbase.master;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.MetaTableAccessor;
import org.apache.hadoop.hbase.ScheduledChore;
import org.apache.hadoop.hbase.Server;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.backup.HFileArchiver;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.FSUtils;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.hadoop.hbase.util.PairOfSameType;
import org.apache.hadoop.hbase.util.Threads;
import org.apache.hadoop.hbase.util.Triple;

/**
 * A janitor for the catalog tables.  Scans the <code>hbase:meta</code> catalog
 * table on a period looking for unused regions to garbage collect.
 */
@InterfaceAudience.Private
public class CatalogJanitor extends ScheduledChore {
  private static final Log LOG = LogFactory.getLog(CatalogJanitor.class.getName());
  private final Server server;
  private final MasterServices services;
  private AtomicBoolean enabled = new AtomicBoolean(true);
  private AtomicBoolean alreadyRunning = new AtomicBoolean(false);
  private final Connection connection;

  CatalogJanitor(final Server server, final MasterServices services) {
    super("CatalogJanitor-" + server.getServerName().toShortString(), server, server
        .getConfiguration().getInt("hbase.catalogjanitor.interval", 300000));
    this.server = server;
    this.services = services;
    this.connection = server.getConnection();
  }

  @Override
  protected boolean initialChore() {
    try {
      if (this.enabled.get()) scan();
    } catch (IOException e) {
      LOG.warn("Failed initial scan of catalog table", e);
      return false;
    }
    return true;
  }

  /**
   * @param enabled
   */
  public boolean setEnabled(final boolean enabled) {
    boolean alreadyEnabled = this.enabled.getAndSet(enabled);
    // If disabling is requested on an already enabled chore, we could have an active
    // scan still going on, callers might not be aware of that and do further action thinkng
    // that no action would be from this chore.  In this case, the right action is to wait for
    // the active scan to complete before exiting this function.
    if (!enabled && alreadyEnabled) {
      while (alreadyRunning.get()) {
        Threads.sleepWithoutInterrupt(100);
      }
    }
    return alreadyEnabled;
  }

  boolean getEnabled() {
    return this.enabled.get();
  }

  @Override
  protected void chore() {
    try {
      AssignmentManager am = this.services.getAssignmentManager();
      if (this.enabled.get()
          && !this.services.isInMaintenanceMode()
          && am != null
          && am.isFailoverCleanupDone()
          && am.getRegionStates().getRegionsInTransition().size() == 0) {
        scan();
      } else {
        LOG.warn("CatalogJanitor disabled! Not running scan.");
      }
    } catch (IOException e) {
      LOG.warn("Failed scan of catalog table", e);
    }
  }

  /**
   * Scans hbase:meta and returns a number of scanned rows, and a map of merged
   * regions, and an ordered map of split parents.
   * @return triple of scanned rows, map of merged regions and map of split
   *         parent regioninfos
   * @throws IOException
   */
  Triple<Integer, Map<HRegionInfo, Result>, Map<HRegionInfo, Result>>
    getMergedRegionsAndSplitParents() throws IOException {
    return getMergedRegionsAndSplitParents(null);
  }

  /**
   * Scans hbase:meta and returns a number of scanned rows, and a map of merged
   * regions, and an ordered map of split parents. if the given table name is
   * null, return merged regions and split parents of all tables, else only the
   * specified table
   * @param tableName null represents all tables
   * @return triple of scanned rows, and map of merged regions, and map of split
   *         parent regioninfos
   * @throws IOException
   */
  Triple<Integer, Map<HRegionInfo, Result>, Map<HRegionInfo, Result>>
    getMergedRegionsAndSplitParents(final TableName tableName) throws IOException {
    final boolean isTableSpecified = (tableName != null);
    // TODO: Only works with single hbase:meta region currently.  Fix.
    final AtomicInteger count = new AtomicInteger(0);
    // Keep Map of found split parents.  There are candidates for cleanup.
    // Use a comparator that has split parents come before its daughters.
    final Map<HRegionInfo, Result> splitParents =
      new TreeMap<HRegionInfo, Result>(new SplitParentFirstComparator());
    final Map<HRegionInfo, Result> mergedRegions = new TreeMap<HRegionInfo, Result>();
    // This visitor collects split parents and counts rows in the hbase:meta table

    MetaTableAccessor.Visitor visitor = new MetaTableAccessor.Visitor() {
      @Override
      public boolean visit(Result r) throws IOException {
        if (r == null || r.isEmpty()) return true;
        count.incrementAndGet();
        HRegionInfo info = MetaTableAccessor.getHRegionInfo(r);
        if (info == null) return true; // Keep scanning
        if (isTableSpecified
            && info.getTable().compareTo(tableName) > 0) {
          // Another table, stop scanning
          return false;
        }
        if (info.isSplitParent()) splitParents.put(info, r);
        if (r.getValue(HConstants.CATALOG_FAMILY, HConstants.MERGEA_QUALIFIER) != null) {
          mergedRegions.put(info, r);
        }
        // Returning true means "keep scanning"
        return true;
      }
    };

    // Run full scan of hbase:meta catalog table passing in our custom visitor with
    // the start row
    MetaTableAccessor.scanMetaForTableRegions(this.connection, visitor, tableName);

    return new Triple<Integer, Map<HRegionInfo, Result>, Map<HRegionInfo, Result>>(
        count.get(), mergedRegions, splitParents);
  }

  /**
   * If merged region no longer holds reference to the merge regions, archive
   * merge region on hdfs and perform deleting references in hbase:meta
   * @param mergedRegion
   * @param regionA
   * @param regionB
   * @return true if we delete references in merged region on hbase:meta and archive
   *         the files on the file system
   * @throws IOException
   */
  boolean cleanMergeRegion(final HRegionInfo mergedRegion,
      final HRegionInfo regionA, final HRegionInfo regionB) throws IOException {
    FileSystem fs = this.services.getMasterFileSystem().getFileSystem();
    Path rootdir = this.services.getMasterFileSystem().getRootDir();
    Path tabledir = FSUtils.getTableDir(rootdir, mergedRegion.getTable());
    HTableDescriptor htd = getTableDescriptor(mergedRegion.getTable());
    HRegionFileSystem regionFs = null;
    try {
      regionFs = HRegionFileSystem.openRegionFromFileSystem(
          this.services.getConfiguration(), fs, tabledir, mergedRegion, true);
    } catch (IOException e) {
      LOG.warn("Merged region does not exist: " + mergedRegion.getEncodedName());
    }
    if (regionFs == null || !regionFs.hasReferences(htd)) {
      LOG.debug("Deleting region " + regionA.getRegionNameAsString() + " and "
          + regionB.getRegionNameAsString()
          + " from fs because merged region no longer holds references");
      HFileArchiver.archiveRegion(this.services.getConfiguration(), fs, regionA);
      HFileArchiver.archiveRegion(this.services.getConfiguration(), fs, regionB);
      MetaTableAccessor.deleteMergeQualifiers(server.getConnection(),
        mergedRegion);
      return true;
    }
    return false;
  }

  /**
   * Run janitorial scan of catalog <code>hbase:meta</code> table looking for
   * garbage to collect.
   * @return number of cleaned regions
   * @throws IOException
   */
  int scan() throws IOException {
    try {
      if (!alreadyRunning.compareAndSet(false, true)) {
        LOG.debug("CatalogJanitor already running");
        return 0;
      }
      Triple<Integer, Map<HRegionInfo, Result>, Map<HRegionInfo, Result>> scanTriple =
        getMergedRegionsAndSplitParents();
      int count = scanTriple.getFirst();
      /**
       * clean merge regions first
       */
      int mergeCleaned = 0;
      Map<HRegionInfo, Result> mergedRegions = scanTriple.getSecond();
      for (Map.Entry<HRegionInfo, Result> e : mergedRegions.entrySet()) {
        if (this.services.isInMaintenanceMode()) {
          // Stop cleaning if the master is in maintenance mode
          break;
        }

        PairOfSameType<HRegionInfo> p = MetaTableAccessor.getMergeRegions(e.getValue());
        HRegionInfo regionA = p.getFirst();
        HRegionInfo regionB = p.getSecond();
        if (regionA == null || regionB == null) {
          LOG.warn("Unexpected references regionA="
              + (regionA == null ? "null" : regionA.getRegionNameAsString())
              + ",regionB="
              + (regionB == null ? "null" : regionB.getRegionNameAsString())
              + " in merged region " + e.getKey().getRegionNameAsString());
        } else {
          if (cleanMergeRegion(e.getKey(), regionA, regionB)) {
            mergeCleaned++;
          }
        }
      }
      /**
       * clean split parents
       */
      Map<HRegionInfo, Result> splitParents = scanTriple.getThird();

      // Now work on our list of found parents. See if any we can clean up.
      int splitCleaned = 0;
      // regions whose parents are still around
      HashSet<String> parentNotCleaned = new HashSet<String>();
      for (Map.Entry<HRegionInfo, Result> e : splitParents.entrySet()) {
        if (this.services.isInMaintenanceMode()) {
          // Stop cleaning if the master is in maintenance mode
          break;
        }

        if (!parentNotCleaned.contains(e.getKey().getEncodedName()) &&
            cleanParent(e.getKey(), e.getValue())) {
          splitCleaned++;
        } else {
          // We could not clean the parent, so it's daughters should not be
          // cleaned either (HBASE-6160)
          PairOfSameType<HRegionInfo> daughters =
              MetaTableAccessor.getDaughterRegions(e.getValue());
          parentNotCleaned.add(daughters.getFirst().getEncodedName());
          parentNotCleaned.add(daughters.getSecond().getEncodedName());
        }
      }
      if ((mergeCleaned + splitCleaned) != 0) {
        LOG.info("Scanned " + count + " catalog row(s), gc'd " + mergeCleaned
            + " unreferenced merged region(s) and " + splitCleaned
            + " unreferenced parent region(s)");
      } else if (LOG.isTraceEnabled()) {
        LOG.trace("Scanned " + count + " catalog row(s), gc'd " + mergeCleaned
            + " unreferenced merged region(s) and " + splitCleaned
            + " unreferenced parent region(s)");
      }
      return mergeCleaned + splitCleaned;
    } finally {
      alreadyRunning.set(false);
    }
  }

  /**
   * Compare HRegionInfos in a way that has split parents sort BEFORE their
   * daughters.
   */
  static class SplitParentFirstComparator implements Comparator<HRegionInfo> {
    Comparator<byte[]> rowEndKeyComparator = new Bytes.RowEndKeyComparator();
    @Override
    public int compare(HRegionInfo left, HRegionInfo right) {
      // This comparator differs from the one HRegionInfo in that it sorts
      // parent before daughters.
      if (left == null) return -1;
      if (right == null) return 1;
      // Same table name.
      int result = left.getTable().compareTo(right.getTable());
      if (result != 0) return result;
      // Compare start keys.
      result = Bytes.compareTo(left.getStartKey(), right.getStartKey());
      if (result != 0) return result;
      // Compare end keys, but flip the operands so parent comes first
      result = rowEndKeyComparator.compare(right.getEndKey(), left.getEndKey());

      return result;
    }
  }

  /**
   * If daughters no longer hold reference to the parents, delete the parent.
   * @param parent HRegionInfo of split offlined parent
   * @param rowContent Content of <code>parent</code> row in
   * <code>metaRegionName</code>
   * @return True if we removed <code>parent</code> from meta table and from
   * the filesystem.
   * @throws IOException
   */
  boolean cleanParent(final HRegionInfo parent, Result rowContent)
  throws IOException {
    boolean result = false;
    // Check whether it is a merged region and not clean reference
    // No necessary to check MERGEB_QUALIFIER because these two qualifiers will
    // be inserted/deleted together
    if (rowContent.getValue(HConstants.CATALOG_FAMILY,
        HConstants.MERGEA_QUALIFIER) != null) {
      // wait cleaning merge region first
      return result;
    }
    // Run checks on each daughter split.
    PairOfSameType<HRegionInfo> daughters = MetaTableAccessor.getDaughterRegions(rowContent);
    Pair<Boolean, Boolean> a = checkDaughterInFs(parent, daughters.getFirst());
    Pair<Boolean, Boolean> b = checkDaughterInFs(parent, daughters.getSecond());
    if (hasNoReferences(a) && hasNoReferences(b)) {
      LOG.debug("Deleting region " + parent.getRegionNameAsString() +
        " because daughter splits no longer hold references");
      FileSystem fs = this.services.getMasterFileSystem().getFileSystem();
      if (LOG.isTraceEnabled()) LOG.trace("Archiving parent region: " + parent);
      HFileArchiver.archiveRegion(this.services.getConfiguration(), fs, parent);
      MetaTableAccessor.deleteRegion(this.connection, parent);
      result = true;
    }
    return result;
  }

  /**
   * @param p A pair where the first boolean says whether or not the daughter
   * region directory exists in the filesystem and then the second boolean says
   * whether the daughter has references to the parent.
   * @return True the passed <code>p</code> signifies no references.
   */
  private boolean hasNoReferences(final Pair<Boolean, Boolean> p) {
    return !p.getFirst() || !p.getSecond();
  }

  /**
   * Checks if a daughter region -- either splitA or splitB -- still holds
   * references to parent.
   * @param parent Parent region
   * @param daughter Daughter region
   * @return A pair where the first boolean says whether or not the daughter
   * region directory exists in the filesystem and then the second boolean says
   * whether the daughter has references to the parent.
   * @throws IOException
   */
  Pair<Boolean, Boolean> checkDaughterInFs(final HRegionInfo parent, final HRegionInfo daughter)
  throws IOException {
    if (daughter == null)  {
      return new Pair<Boolean, Boolean>(Boolean.FALSE, Boolean.FALSE);
    }

    FileSystem fs = this.services.getMasterFileSystem().getFileSystem();
    Path rootdir = this.services.getMasterFileSystem().getRootDir();
    Path tabledir = FSUtils.getTableDir(rootdir, daughter.getTable());

    Path daughterRegionDir = new Path(tabledir, daughter.getEncodedName());

    HRegionFileSystem regionFs = null;

    try {
      if (!FSUtils.isExists(fs, daughterRegionDir)) {
        return new Pair<Boolean, Boolean>(Boolean.FALSE, Boolean.FALSE);
      }
    } catch (IOException ioe) {
      LOG.warn("Error trying to determine if daughter region exists, " +
               "assuming exists and has references", ioe);
      return new Pair<Boolean, Boolean>(Boolean.TRUE, Boolean.TRUE);
    }

    try {
      regionFs = HRegionFileSystem.openRegionFromFileSystem(
          this.services.getConfiguration(), fs, tabledir, daughter, true);
    } catch (IOException e) {
      LOG.warn("Error trying to determine referenced files from : " + daughter.getEncodedName()
          + ", to: " + parent.getEncodedName() + " assuming has references", e);
      return new Pair<Boolean, Boolean>(Boolean.TRUE, Boolean.TRUE);
    }

    boolean references = false;
    HTableDescriptor parentDescriptor = getTableDescriptor(parent.getTable());
    for (HColumnDescriptor family: parentDescriptor.getFamilies()) {
      if ((references = regionFs.hasReferences(family.getNameAsString()))) {
        break;
      }
    }
    return new Pair<Boolean, Boolean>(Boolean.TRUE, Boolean.valueOf(references));
  }

  private HTableDescriptor getTableDescriptor(final TableName tableName)
      throws FileNotFoundException, IOException {
    return this.services.getTableDescriptors().get(tableName);
  }

  /**
   * Checks if the specified region has merge qualifiers, if so, try to clean
   * them
   * @param region
   * @return true if the specified region doesn't have merge qualifier now
   * @throws IOException
   */
  public boolean cleanMergeQualifier(final HRegionInfo region)
      throws IOException {
    // Get merge regions if it is a merged region and already has merge
    // qualifier
    Pair<HRegionInfo, HRegionInfo> mergeRegions = MetaTableAccessor
        .getRegionsFromMergeQualifier(this.services.getConnection(),
          region.getRegionName());
    if (mergeRegions == null
        || (mergeRegions.getFirst() == null && mergeRegions.getSecond() == null)) {
      // It doesn't have merge qualifier, no need to clean
      return true;
    }
    // It shouldn't happen, we must insert/delete these two qualifiers together
    if (mergeRegions.getFirst() == null || mergeRegions.getSecond() == null) {
      LOG.error("Merged region " + region.getRegionNameAsString()
          + " has only one merge qualifier in META.");
      return false;
    }
    return cleanMergeRegion(region, mergeRegions.getFirst(),
        mergeRegions.getSecond());
  }
}