public int repair(MsckInfo msckInfo) throws TException, MetastoreException, IOException {
    CheckResult result = null;
    List<String> repairOutput = new ArrayList<>();
    String qualifiedTableName = null;
    boolean success = false;
    long txnId = -1;
    long partitionExpirySeconds = -1;
    try {
      Table table = getMsc().getTable(msckInfo.getCatalogName(), msckInfo.getDbName(), msckInfo.getTableName());
      partitionExpirySeconds = PartitionManagementTask.getRetentionPeriodInSeconds(table);
      qualifiedTableName = Warehouse.getCatalogQualifiedTableName(table);
      HiveMetaStoreChecker checker = new HiveMetaStoreChecker(getMsc(), getConf(), partitionExpirySeconds);
      // checkMetastore call will fill in result with partitions that are present in filesystem
      // and missing in metastore - accessed through getPartitionsNotInMs
      // And partitions that are not present in filesystem and metadata exists in metastore -
      // accessed through getPartitionNotOnFS
      result = checker.checkMetastore(msckInfo.getCatalogName(), msckInfo.getDbName(), msckInfo.getTableName(),
        msckInfo.getFilterExp(), table);
      Set<CheckResult.PartitionResult> partsNotInMs = result.getPartitionsNotInMs();
      Set<CheckResult.PartitionResult> partsNotInFs = result.getPartitionsNotOnFs();
      Set<CheckResult.PartitionResult> expiredPartitions = result.getExpiredPartitions();
      int totalPartsToFix = partsNotInMs.size() + partsNotInFs.size() + expiredPartitions.size();
      // if nothing changed to partitions and if we are not repairing (add or drop) don't acquire for lock unnecessarily
      boolean lockRequired = totalPartsToFix > 0 &&
        msckInfo.isRepairPartitions() &&
        (msckInfo.isAddPartitions() || msckInfo.isDropPartitions());
      LOG.info("{} - #partsNotInMs: {} #partsNotInFs: {} #expiredPartitions: {} lockRequired: {} (R: {} A: {} D: {})",
        qualifiedTableName, partsNotInMs.size(), partsNotInFs.size(), expiredPartitions.size(), lockRequired,
        msckInfo.isRepairPartitions(), msckInfo.isAddPartitions(), msckInfo.isDropPartitions());

      if (msckInfo.isRepairPartitions()) {
        boolean transactionalTable = TxnUtils.isTransactionalTable(table);
        // Repair metadata in HMS
        long lockId;
        if (acquireLock && lockRequired && table.getParameters() != null && transactionalTable) {
          // Running MSCK from beeline/cli will make DDL task acquire X lock when repair is enabled, since we are directly
          // invoking msck.repair() without SQL statement, we need to do the same and acquire X lock (repair is default)
          LockRequest lockRequest = createLockRequest(msckInfo.getDbName(), msckInfo.getTableName());
          txnId = lockRequest.getTxnid();
          try {
            LockResponse res = getMsc().lock(lockRequest);
            if (res.getState() != LockState.ACQUIRED) {
              throw new MetastoreException("Unable to acquire lock(X) on " + qualifiedTableName);
            }
            lockId = res.getLockid();
          } catch (TException e) {
            throw new MetastoreException("Unable to acquire lock(X) on " + qualifiedTableName, e);
          }
          LOG.info("Acquired lock(X) on {}. LockId: {}", qualifiedTableName, lockId);
        }
        int maxRetries = MetastoreConf.getIntVar(getConf(), MetastoreConf.ConfVars.MSCK_REPAIR_BATCH_MAX_RETRIES);
        int decayingFactor = 2;

        if (msckInfo.isAddPartitions() && !partsNotInMs.isEmpty()) {
          // MSCK called to add missing paritions into metastore and there are
          // missing partitions.

          int batchSize = MetastoreConf.getIntVar(getConf(), MetastoreConf.ConfVars.MSCK_REPAIR_BATCH_SIZE);
          if (batchSize == 0) {
            //batching is not enabled. Try to add all the partitions in one call
            batchSize = partsNotInMs.size();
          }

          AbstractList<String> vals = null;
          String settingStr = MetastoreConf.getVar(getConf(), MetastoreConf.ConfVars.MSCK_PATH_VALIDATION);
          boolean doValidate = !("ignore".equals(settingStr));
          boolean doSkip = doValidate && "skip".equals(settingStr);
          // The default setting is "throw"; assume doValidate && !doSkip means throw.
          if (doValidate) {
            // Validate that we can add partition without escaping. Escaping was originally intended
            // to avoid creating invalid HDFS paths; however, if we escape the HDFS path (that we
            // deem invalid but HDFS actually supports - it is possible to create HDFS paths with
            // unprintable characters like ASCII 7), metastore will create another directory instead
            // of the one we are trying to "repair" here.
            Iterator<CheckResult.PartitionResult> iter = partsNotInMs.iterator();
            while (iter.hasNext()) {
              CheckResult.PartitionResult part = iter.next();
              try {
                vals = Warehouse.makeValsFromName(part.getPartitionName(), vals);
              } catch (MetaException ex) {
                throw new MetastoreException(ex);
              }
              for (String val : vals) {
                String escapedPath = FileUtils.escapePathName(val);
                assert escapedPath != null;
                if (escapedPath.equals(val)) {
                  continue;
                }
                String errorMsg = "Repair: Cannot add partition " + msckInfo.getTableName() + ':' +
                  part.getPartitionName() + " due to invalid characters in the name";
                if (doSkip) {
                  repairOutput.add(errorMsg);
                  iter.remove();
                } else {
                  throw new MetastoreException(errorMsg);
                }
              }
            }
          }
          if (transactionalTable) {
            if (txnId < 0) {
              // We need the txnId to check against even if we didn't do the locking
              txnId = getMsc().openTxn(getUserName());
            }
            // If we add new partitions to a transactional table, we have to repair the writeIds in the HMS
            validateAndAddMaxTxnIdAndWriteId(partsNotInMs, table.getDbName(), table.getTableName(), txnId);
          }
          try {
            createPartitionsInBatches(getMsc(), repairOutput, partsNotInMs, table, batchSize,
              decayingFactor, maxRetries);
          } catch (Exception e) {
            throw new MetastoreException(e);
          }
        }

        if (msckInfo.isDropPartitions() && (!partsNotInFs.isEmpty() || !expiredPartitions.isEmpty())) {
          // MSCK called to drop stale paritions from metastore and there are
          // stale partitions.

          int batchSize = MetastoreConf.getIntVar(getConf(), MetastoreConf.ConfVars.MSCK_REPAIR_BATCH_SIZE);
          if (batchSize == 0) {
            //batching is not enabled. Try to drop all the partitions in one call
            batchSize = partsNotInFs.size() + expiredPartitions.size();
          }

          try {
            dropPartitionsInBatches(getMsc(), repairOutput, partsNotInFs, expiredPartitions, table, batchSize,
              decayingFactor, maxRetries);
          } catch (Exception e) {
            throw new MetastoreException(e);
          }
        }
        if (transactionalTable && !MetaStoreServerUtils.isPartitioned(table) && result.getMaxWriteId() > 0) {
          if (txnId < 0) {
            // We need the txnId to check against even if we didn't do the locking
            txnId = getMsc().openTxn(getUserName());
          }

          validateAndAddMaxTxnIdAndWriteId(result.getMaxWriteId(), result.getMaxTxnId(), table.getDbName(),
              table.getTableName(), txnId);
        }
      }
      success = true;
    } catch (Exception e) {
      LOG.warn("Failed to run metacheck: ", e);
      success = false;
      throw e;
    } finally {
      if (result != null) {
        logResult(result);
        if (msckInfo.getResFile() != null) {
          // sorting to stabilize qfile output (msck_repair_drop.q)
          Collections.sort(repairOutput);
          success &= writeResultToFile(msckInfo, result, repairOutput, partitionExpirySeconds);
        }
      }

      if (txnId > 0) {
        success &= closeTxn(qualifiedTableName, success, txnId);
      }
      if (getMsc() != null) {
        getMsc().close();
        msc = null;
      }
    }
    return success ? 0 : 1;
  }
MetastoreCheck, see if the data in the metastore matches what is on the
dfs. Current version checks for tables and partitions that are either
missing on disk on in the metastore.

@param msckInfo Information about the tables and partitions we want to check for.
@return Returns 0 when execution succeeds and above 0 if it fails.
standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/Msck.java