void checkTable(Table table, PartitionIterable parts, byte[] filterExp, CheckResult result) throws IOException,
    MetastoreException, MetaException {

    Path tablePath = getPath(table);
    if (tablePath == null) {
      return;
    }
    FileSystem fs = tablePath.getFileSystem(conf);
    if (!fs.exists(tablePath)) {
      result.getTablesNotOnFs().add(table.getTableName());
      return;
    }

    // now check the table folder and see if we find anything
    // that isn't in the metastore
    Set<Path> allPartDirs = new HashSet<>();
    List<FieldSchema> partColumns = table.getPartitionKeys();
    checkPartitionDirs(tablePath, allPartDirs, Collections.unmodifiableList(getPartColNames(table)));
    String tablePathStr = tablePath.toString();
    int tablePathLength = tablePathStr.length();

    if (filterExp != null) {
      PartitionExpressionProxy expressionProxy = createExpressionProxy(conf);
      List<String> partitions = new ArrayList<>();
      Set<Path> partDirs = new HashSet<Path>();
      boolean tablePathStrEndsWith = tablePathStr.endsWith("/");
      int tablePathStrLen = tablePathStr.endsWith("/") ? tablePathStr.length() : tablePathStr.length() + 1;
      allPartDirs.stream().forEach(path -> partitions.add(path.toString().substring(tablePathStrLen)));

      // Remove all partition paths which does not matches the filter expression.
      expressionProxy.filterPartitionsByExpr(partColumns, filterExp,
              conf.get(MetastoreConf.ConfVars.DEFAULTPARTITIONNAME.getVarname()), partitions);

      // now the partition list will contain all the paths that matches the filter expression.
      // add them back to partDirs.
      for (String path : partitions) {
        partDirs.add(new Path(tablePath, path));
      }
      allPartDirs = partDirs;
    }

    // check that the partition folders exist on disk
    for (Partition partition : parts) {
      if (partition == null) {
        // most likely the user specified an invalid partition
        continue;
      }
      Path partPath = getDataLocation(table, partition);
      if (partPath == null) {
        continue;
      }
      fs = partPath.getFileSystem(conf);

      CheckResult.PartitionResult prFromMetastore = new CheckResult.PartitionResult();
      prFromMetastore.setPartitionName(getPartitionName(table, partition));
      prFromMetastore.setTableName(partition.getTableName());
      if (allPartDirs.remove(partPath)) {
        result.getCorrectPartitions().add(prFromMetastore);
      } else {
        // There can be edge case where user can define partition directory outside of table directory
        // to avoid eviction of such partitions
        // we check existence of partition path which are not in table directory
        if (!partPath.toString().contains(tablePathStr)) {
          if (!fs.exists(partPath)) {
            result.getPartitionsNotOnFs().add(prFromMetastore);
          } else {
            result.getCorrectPartitions().add(prFromMetastore);
          }
        } else {
          // If Partition Path contains table path, we assume to be non-existent partition since
          // Partition spec has to be in format FS://<TablePath>/<PartKeyName>=<PartValue>
          // otherwise partition discovery may fail.
          result.getPartitionsNotOnFs().add(prFromMetastore);
        }
      }

      if (partitionExpirySeconds > 0) {
        long currentEpochSecs = Instant.now().getEpochSecond();
        long createdTime = partition.getCreateTime();
        long partitionAgeSeconds = currentEpochSecs - createdTime;
        if (partitionAgeSeconds > partitionExpirySeconds) {
          CheckResult.PartitionResult pr = new CheckResult.PartitionResult();
          pr.setPartitionName(getPartitionName(table, partition));
          pr.setTableName(partition.getTableName());
          result.getExpiredPartitions().add(pr);
          if (LOG.isDebugEnabled()) {
            LOG.debug("{}.{}.{}.{} expired. createdAt: {} current: {} age: {}s expiry: {}s", table.getCatName(),
                table.getDbName(), partition.getTableName(), pr.getPartitionName(), createdTime, currentEpochSecs,
                partitionAgeSeconds, partitionExpirySeconds);
          }
        }
      }
    }

    findUnknownPartitions(table, allPartDirs, result);

    if (!isPartitioned(table) && TxnUtils.isTransactionalTable(table)) {
      // Check for writeIds in the table directory
      CheckResult.PartitionResult tableResult = new CheckResult.PartitionResult();
      setMaxTxnAndWriteIdFromPartition(tablePath, tableResult);
      result.setMaxWriteId(tableResult.getMaxWriteId());
      result.setMaxTxnId(tableResult.getMaxTxnId());
    }
  }
Check the metastore for inconsistencies, data missing in either the
metastore or on the dfs.

@param table
         Table to check
@param parts
         Partitions to check
@param result
         Result object
@param filterExp
         Filter expression which is used to prune th partition from the
         metastore and FileSystem.
@throws IOException
          Could not get information from filesystem
@throws MetastoreException
          Could not create Partition object
standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HiveMetaStoreChecker.java