private Partition constructPartition(
      JobContext context, OutputJobInfo jobInfo,
      String partLocnRoot, String dynPartPath, Map<String, String> partKVs,
      HCatSchema outputSchema, Map<String, String> params,
      Table table, FileSystem fs, HiveConf conf,
      HdfsUtils.HadoopFileStatus status) throws IOException {

    Partition partition = new Partition();
    partition.setDbName(table.getDbName());
    partition.setTableName(table.getTableName());
    partition.setSd(new StorageDescriptor(table.getTTable().getSd()));

    List<FieldSchema> fields = new ArrayList<FieldSchema>();
    for (HCatFieldSchema fieldSchema : outputSchema.getFields()) {
      fields.add(HCatSchemaUtils.getFieldSchema(fieldSchema));
    }

    partition.getSd().setCols(fields);

    partition.setValues(FileOutputFormatContainer.getPartitionValueList(table, partKVs));

    partition.setParameters(params);

    // Sets permissions and group name on partition dirs and files.

    Path partPath;
    if (customDynamicLocationUsed) {
      partPath = new Path(dynPartPath);
    } else if (!dynamicPartitioningUsed
         && Boolean.parseBoolean((String)table.getProperty("EXTERNAL"))
         && jobInfo.getLocation() != null && jobInfo.getLocation().length() > 0) {
      // Now, we need to de-scratchify this location - i.e., get rid of any
      // _SCRATCH[\d].?[\d]+ from the location.
      String jobLocation = jobInfo.getLocation();
      String finalLocn = jobLocation.replaceAll(Path.SEPARATOR + SCRATCH_DIR_NAME + "\\d\\.?\\d+","");
      partPath = new Path(finalLocn);
    } else {
      partPath = new Path(partLocnRoot);
      FileSystem partFs = partPath.getFileSystem(context.getConfiguration());
      int i = 0;
      for (FieldSchema partKey : table.getPartitionKeys()) {
        if (i++ != 0) {
          partFs.mkdirs(partPath); // Attempt to make the path in case it does not exist before we check
          HdfsUtils.setFullFileStatus(conf, status, status.getFileStatus().getGroup(), fs,
              partPath, false);
        }
        partPath = constructPartialPartPath(partPath, partKey.getName().toLowerCase(), partKVs);
      }
    }

    // Do not need to set the status on the partition directory. We will do it later recursively.
    // See: end of the registerPartitions method
    FileSystem partFs = partPath.getFileSystem(context.getConfiguration());
    partFs.mkdirs(partPath);

    // Set the location in the StorageDescriptor
    if (dynamicPartitioningUsed) {
      String dynamicPartitionDestination = getFinalDynamicPartitionDestination(table, partKVs, jobInfo);
      if (harProcessor.isEnabled()) {
        harProcessor.exec(context, partition, partPath);
        partition.getSd().setLocation(
          harProcessor.getProcessedLocation(new Path(dynamicPartitionDestination)));
      } else {
        partition.getSd().setLocation(dynamicPartitionDestination);
      }
    } else {
      partition.getSd().setLocation(partPath.toString());
    }
    return partition;
  }
Generate partition metadata object to be used to add to metadata.
@param context The job context.
@param jobInfo The OutputJobInfo.
@param partLocnRoot The table-equivalent location root of the partition
                      (temporary dir if dynamic partition, table dir if static)
@param dynPartPath The path of dynamic partition which is created
@param partKVs The keyvalue pairs that form the partition
@param outputSchema The output schema for the partition
@param params The parameters to store inside the partition
@param table The Table metadata object under which this Partition will reside
@param fs FileSystem object to operate on the underlying filesystem
@param conf HiveConf used to access FS
@param status Permission that's the default permission of the table dir.
@return Constructed Partition metadata object
@throws java.io.IOException
hcatalog/core/src/main/java/org/apache/hive/hcatalog/mapreduce/FileOutputCommitterContainer.java