/**
 * 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.hdfs.server.namenode;

import com.google.protobuf.ByteString;
import org.apache.hadoop.fs.InvalidPathException;
import org.apache.hadoop.fs.PathIsNotEmptyDirectoryException;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.server.namenode.INode.BlocksMapUpdateInfo;
import org.apache.hadoop.util.ChunkedArrayList;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;

import static org.apache.hadoop.util.Time.now;

class FSDirDeleteOp {
  /**
   * Delete the target directory and collect the blocks under it
   *
   * @param tx the Transaction
   * @param paths the path to be deleted
   * @param collectedBlocks Blocks under the deleted directory
   * @return the number of files that have been removed
   */
  static long delete(
      RWTransaction tx, Resolver.Result paths,
      BlocksMapUpdateInfo collectedBlocks, List<Long> removedUCFiles, long mtime) throws IOException {
    if (NameNode.stateChangeLog.isDebugEnabled()) {
      NameNode.stateChangeLog.debug("DIR* FSDirectory.delete: " + paths.src);
    }
    final long filesRemoved;
    if (!deleteAllowed(paths)) {
      filesRemoved = -1;
    } else {
      filesRemoved = unprotectedDelete(tx, paths, collectedBlocks,
                                       removedUCFiles, mtime);
    }
    return filesRemoved;
  }

  /**
   * Remove a file/directory from the namespace.
   * <p>
   * For large directories, deletion is incremental. The blocks under
   * the directory are collected and deleted a small number at a time holding
   * the {@link FSNamesystem} lock.
   * <p>
   * For small directory or file the deletion is done in one shot.
   *
   * @param fsn namespace
   * @param src path name to be deleted
   * @param recursive boolean true to apply to all sub-directories recursively
   * @param logRetryCache whether to record RPC ids in editlog for retry cache
   *          rebuilding
   * @return blocks collected from the deleted path
   * @throws IOException
   */
  static BlocksMapUpdateInfo delete(
      FSNamesystem fsn, String src, boolean recursive, boolean logRetryCache)
      throws IOException {
    FSDirectory fsd = fsn.getFSDirectory();
    FSPermissionChecker pc = fsd.getPermissionChecker();
    try (RWTransaction tx = fsd.newRWTransaction().begin()) {
      Resolver.Result paths = Resolver.resolve(tx, src);
      if (paths.notFound()) {
        // The caller expects no exception when the file does not exist
        return null;
      } else if (paths.invalidPath()) {
        throw new InvalidPathException(src);
      }

      FlatINodesInPath iip = paths.inodesInPath();
      if (!recursive && FSDirectory.isNonEmptyDirectory(tx, iip)) {
        throw new PathIsNotEmptyDirectoryException(src + " is non empty");
      }

      if (fsd.isPermissionEnabled()) {
        fsd.checkPermission(pc, iip, false, null, FsAction.WRITE, null,
                            FsAction.ALL, true);
      }
      BlocksMapUpdateInfo ret = deleteInternal(tx, fsn, paths, logRetryCache);
      tx.commit();
      return ret;
    }

  }

  /**
   * Delete a path from the name space
   * Update the count at each ancestor directory with quota
   * <br>
   * Note: This is to be used by
   * {@link org.apache.hadoop.hdfs.server.namenode.FSEditLog} only.
   * <br>
   *
   * @param fsd the FSDirectory instance
   * @param src a string representation of a path to an inode
   * @param mtime the time the inode is removed
   */
  static void deleteForEditLog(FSDirectory fsd, String src, long mtime)
      throws IOException {
    FSNamesystem fsn = fsd.getFSNamesystem();
    BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo();
    List<Long> removedINodes = new ChunkedArrayList<>();
    List<Long> removedUCFiles = new ChunkedArrayList<>();
    try (ReplayTransaction tx = fsd.newReplayTransaction().begin()) {
      Resolver.Result paths = Resolver.resolve(tx, src);
      if (!deleteAllowed(paths)) {
        return;
      }
      long filesRemoved = unprotectedDelete(tx, paths, collectedBlocks,
                                            removedUCFiles, mtime);
      if (filesRemoved >= 0) {
        fsn.removeLeases(removedUCFiles);
        fsn.removeBlocksAndUpdateSafemodeTotal(collectedBlocks);
      }
      tx.commit();
    }
  }

  /**
   * Remove a file/directory from the namespace.
   * <p>
   * For large directories, deletion is incremental. The blocks under
   * the directory are collected and deleted a small number at a time holding
   * the {@link org.apache.hadoop.hdfs.server.namenode.FSNamesystem} lock.
   * <p>
   * For small directory or file the deletion is done in one shot.
   * @param fsn namespace
   * @param paths the path to be deleted
   * @param logRetryCache whether to record RPC ids in editlog for retry cache
   *          rebuilding
   * @return blocks collected from the deleted path
   * @throws IOException
   */
  static BlocksMapUpdateInfo deleteInternal(
      RWTransaction tx, FSNamesystem fsn, Resolver.Result paths,
      boolean logRetryCache)
      throws IOException {
    if (NameNode.stateChangeLog.isDebugEnabled()) {
      NameNode.stateChangeLog.debug("DIR* NameSystem.delete: " + paths.src);
    }

    FSDirectory fsd = fsn.getFSDirectory();
    BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo();
    List<Long> removedINodes = new ChunkedArrayList<>();
    List<Long> removedUCFiles = new ChunkedArrayList<>();

    long mtime = now();
    // Unlink the target directory from directory tree
    long filesRemoved = delete(tx, paths, collectedBlocks, removedUCFiles,
                               mtime);
    if (filesRemoved < 0) {
      return null;
    }
    fsd.getEditLog().logDelete(paths.src, mtime, logRetryCache);
    incrDeletedFileCount(filesRemoved);

    fsn.removeLeases(removedUCFiles);

    if (NameNode.stateChangeLog.isDebugEnabled()) {
      NameNode.stateChangeLog.debug(
          "DIR* Namesystem.delete: " + paths.src + " is removed");
    }
    return collectedBlocks;
  }

  static void incrDeletedFileCount(long count) {
    NameNode.getNameNodeMetrics().incrFilesDeleted(count);
  }

  private static boolean deleteAllowed(Resolver.Result paths) {
    String src = paths.src;
    if (paths.notFound()) {
      if (NameNode.stateChangeLog.isDebugEnabled()) {
        NameNode.stateChangeLog.debug(
            "DIR* FSDirectory.unprotectedDelete: failed to remove "
                + src + " because it does not exist");
      }
      return false;
    } else if (paths.inodesInPath().length() == 1) { // src is the root
      NameNode.stateChangeLog.warn(
          "DIR* FSDirectory.unprotectedDelete: failed to remove " + src +
              " because the root is not allowed to be deleted");
      return false;
    }
    return true;
  }

  /**
   * Delete a path from the name space
   * Update the count at each ancestor directory with quota
   *
   * @param tx Transaction
   * @param paths the path to be deleted
   * @param collectedBlocks blocks collected from the deleted path
   * @param removedUCFiles inodes whose leases need to be released
   * @param mtime the time the inode is removed
   * @return true if there are inodes deleted
   */
  private static long unprotectedDelete(
      RWTransaction tx, Resolver.Result paths,
      BlocksMapUpdateInfo collectedBlocks, List<Long> removedUCFiles, long mtime)
      throws IOException {
    // TODO: Update quota
    FlatINode parent = paths.inodesInPath().getLastINode(-2);
    FlatINode inode = paths.inodesInPath().getLastINode();
    long deleted = deleteSubtree(tx, inode.id(), collectedBlocks,
                                 removedUCFiles);
    ByteString newParent = new FlatINode.Builder()
        .mergeFrom(parent).mtime(mtime).build();
    tx.putINode(parent.id(), newParent);
    tx.deleteChild(parent.id(),
                   paths.inodesInPath().getLastPathComponent().asReadOnlyByteBuffer());
    if (NameNode.stateChangeLog.isDebugEnabled()) {
      NameNode.stateChangeLog.debug("DIR* FSDirectory.unprotectedDelete: "
          + paths.src + " is removed");
    }
    return deleted + 1;
  }

  private static long deleteSubtree(
      RWTransaction tx, long parentId, BlocksMapUpdateInfo collectedBlocks,
      List<Long> removedUCFiles) throws IOException {
    long deleted = 0;
    try (DBChildrenView children = tx.childrenView(parentId)) {
      for (Map.Entry<ByteBuffer, Long> e : children) {
        long child = e.getValue();
        FlatINode node = tx.getINode(child);
        if (node.isFile()) {
          FlatINodeFileFeature f = node.feature(FlatINodeFileFeature.class);
          assert f != null;
          if (f.inConstruction()) {
            removedUCFiles.add(child);
          }
          for (Block b : f.blocks()) {
            collectedBlocks.addDeleteBlock(b);
          }
        } else if (node.isDirectory()) {
          deleted += deleteSubtree(tx, child, collectedBlocks, removedUCFiles);
        }
      }
    }
    return deleted;
  }
}
