private void registerPartitions(JobContext context) throws IOException{
    if (dynamicPartitioningUsed){
      discoverPartitions(context);
    }
    OutputJobInfo jobInfo = HCatOutputFormat.getJobInfo(context.getConfiguration());
    Configuration conf = context.getConfiguration();
    Table table = new Table(jobInfo.getTableInfo().getTable());
    Path tblPath = new Path(table.getTTable().getSd().getLocation());
    FileSystem fs = tblPath.getFileSystem(conf);
    IMetaStoreClient client = null;
    HCatTableInfo tableInfo = jobInfo.getTableInfo();
    List<Partition> partitionsAdded = new ArrayList<Partition>();
    try {
      HiveConf hiveConf = HCatUtil.getHiveConf(conf);
      client = HCatUtil.getHiveMetastoreClient(hiveConf);
      if (table.getPartitionKeys().size() == 0) {
        // Move data from temp directory the actual table directory
        // No metastore operation required.
        Path src = new Path(jobInfo.getLocation());
        moveTaskOutputs(conf, src, src, tblPath, table.isImmutable());
        if (!src.equals(tblPath)) {
          fs.delete(src, true);
        }
        if (table.getParameters() != null
            && table.getParameters().containsKey(StatsSetupConst.COLUMN_STATS_ACCURATE)) {
          table.getParameters().remove(StatsSetupConst.COLUMN_STATS_ACCURATE);
          client.alter_table(table.getDbName(), table.getTableName(), table.getTTable());
        }
        return;
      }

      StorerInfo storer = InternalUtil.extractStorerInfo(table.getTTable().getSd(),
          table.getParameters());

      HdfsUtils.HadoopFileStatus status = HdfsUtils.HadoopFileStatus.createInstance(conf, fs, tblPath);

      List<Partition> partitionsToAdd = new ArrayList<Partition>();
      if (!dynamicPartitioningUsed) {
        partitionsToAdd.add(constructPartition(context, jobInfo, tblPath.toString(), null,
            jobInfo.getPartitionValues(), jobInfo.getOutputSchema(), getStorerParameterMap(storer),
            table, fs, hiveConf, status));
      } else {
        for (Entry<String, Map<String, String>> entry : partitionsDiscoveredByPath.entrySet()) {
          partitionsToAdd.add(constructPartition(context, jobInfo,
              getPartitionRootLocation(entry.getKey(), entry.getValue().size()), entry.getKey(),
              entry.getValue(), jobInfo.getOutputSchema(), getStorerParameterMap(storer), table,
              fs, hiveConf, status));
        }
      }

      ArrayList<Map<String,String>> ptnInfos = new ArrayList<Map<String,String>>();
      for(Partition ptn : partitionsToAdd){
        ptnInfos.add(InternalUtil.createPtnKeyValueMap(new Table(tableInfo.getTable()), ptn));
      }

      /**
       * Dynamic partitioning & Append incompatibility note:
       *
       * Currently, we do not support mixing dynamic partitioning and append in the
       * same job. One reason is that we need exhaustive testing of corner cases
       * for that, and a second reason is the behaviour of add_partitions. To support
       * dynamic partitioning with append, we'd have to have a add_partitions_if_not_exist
       * call, rather than an add_partitions call. Thus far, we've tried to keep the
       * implementation of append jobtype-agnostic, but here, in code, we assume that
       * a table is considered immutable if dynamic partitioning is enabled on the job.
       *
       * This does not mean that we can check before the job begins that this is going
       * to be a dynamic partition job on an immutable table and thus fail the job, since
       * it is quite possible to have a dynamic partitioning job run on an unpopulated
       * immutable table. It simply means that at the end of the job, as far as copying
       * in data is concerned, we will pretend that the table is immutable irrespective
       * of what table.isImmutable() tells us.
       */

      //Publish the new partition(s)
      if (dynamicPartitioningUsed && harProcessor.isEnabled() && (!partitionsToAdd.isEmpty())){

        if (!customDynamicLocationUsed) {
          Path src = new Path(ptnRootLocation);
          // check here for each dir we're copying out, to see if it
          // already exists, error out if so.
          // Also, treat dyn-writes as writes to immutable tables.
          moveTaskOutputs(conf, src, src, tblPath, table.isImmutable());
          if (!src.equals(tblPath)){
            fs.delete(src, true);
          }
        } else {
          moveCustomLocationTaskOutputs(fs, table, hiveConf);
        }
        try {
          updateTableSchema(client, table, jobInfo.getOutputSchema());
          LOG.info("HAR is being used. The table {} has new partitions {}.", table.getTableName(), ptnInfos);
          client.add_partitions(partitionsToAdd);
          partitionsAdded = partitionsToAdd;
        } catch (Exception e){
          // There was an error adding partitions : rollback fs copy and rethrow
          for (Partition p : partitionsToAdd){
            Path ptnPath = new Path(harProcessor.getParentFSPath(new Path(p.getSd().getLocation())));
            if (fs.exists(ptnPath)){
              fs.delete(ptnPath,true);
            }
          }
          throw e;
        }

      }else{

        // no harProcessor, regular operation
        updateTableSchema(client, table, jobInfo.getOutputSchema());
        LOG.info("HAR not is not being used. The table {} has new partitions {}.", table.getTableName(), ptnInfos);
        if (partitionsToAdd.size() > 0){
          if (!dynamicPartitioningUsed ) {

            // regular single-partition write into a partitioned table.
            //Move data from temp directory the actual table directory
            if (partitionsToAdd.size() > 1){
              throw new HCatException(ErrorType.ERROR_PUBLISHING_PARTITION,
                  "More than one partition to publish in non-dynamic partitioning job");
            }
            Partition p = partitionsToAdd.get(0);
            Path src = new Path(jobInfo.getLocation());
            Path dest = new Path(p.getSd().getLocation());
            moveTaskOutputs(conf, src, src, dest, table.isImmutable());
            if (!src.equals(dest)){
              if (src.toString().matches(".*" + Path.SEPARATOR + SCRATCH_DIR_NAME + "\\d\\.?\\d+.*")){
                // src is scratch directory, need to trim the part key value pairs from path
                String diff = StringUtils.difference(src.toString(), dest.toString());
                fs.delete(new Path(StringUtils.substringBefore(src.toString(), diff)), true);
              } else {
                fs.delete(src, true);
              }
            }

            // Now, we check if the partition already exists. If not, we go ahead.
            // If so, we error out if immutable, and if mutable, check that the partition's IF
            // matches our current job's IF (table's IF) to check for compatibility. If compatible, we
            // ignore and do not add. If incompatible, we error out again.

            boolean publishRequired = false;
            try {
              Partition existingP = client.getPartition(p.getDbName(),p.getTableName(),p.getValues());
              if (existingP != null){
                if (table.isImmutable()){
                  throw new HCatException(ErrorType.ERROR_DUPLICATE_PARTITION,
                      "Attempted duplicate partition publish on to immutable table");
                } else {
                  if (! existingP.getSd().getInputFormat().equals(table.getInputFormatClass().getName())){
                    throw new HCatException(ErrorType.ERROR_PUBLISHING_PARTITION,
                        "Attempted partition append, where old partition format was "
                            + existingP.getSd().getInputFormat()
                            + " and table format was "
                            + table.getInputFormatClass().getName());
                  }
                }
              } else {
                publishRequired = true;
              }
            } catch (NoSuchObjectException e){
              // All good, no such partition exists, move on.
              publishRequired = true;
            }
            if (publishRequired){
              client.add_partitions(partitionsToAdd);
              partitionsAdded = partitionsToAdd;
            }

          } else {
            // Dynamic partitioning usecase
            if (!customDynamicLocationUsed) {
              Path src = new Path(ptnRootLocation);
              moveTaskOutputs(conf, src, src, tblPath, true);
              if (!src.equals(tblPath)){
                fs.delete(src, true);
              }
            } else {
              moveCustomLocationTaskOutputs(fs, table, hiveConf);
            }
            client.add_partitions(partitionsToAdd);
            partitionsAdded = partitionsToAdd;
          }
        }

        // Set permissions appropriately for each of the partitions we just created
        // so as to have their permissions mimic the table permissions
        for (Partition p : partitionsAdded){
          HdfsUtils.setFullFileStatus(conf, status, status.getFileStatus().getGroup(), fs,
              new Path(p.getSd().getLocation()), true);
        }
      }
    } catch (Exception e) {
      if (partitionsAdded.size() > 0) {
        try {
          // baseCommitter.cleanupJob failed, try to clean up the
          // metastore
          for (Partition p : partitionsAdded) {
            client.dropPartition(tableInfo.getDatabaseName(),
                tableInfo.getTableName(), p.getValues(), true);
          }
        } catch (Exception te) {
          // Keep cause as the original exception
          throw new HCatException(
              ErrorType.ERROR_PUBLISHING_PARTITION, e);
        }
      }
      if (e instanceof HCatException) {
        throw (HCatException) e;
      } else {
        throw new HCatException(ErrorType.ERROR_PUBLISHING_PARTITION, e);
      }
    } finally {
      HCatUtil.closeHiveClientQuietly(client);
    }
  }
Run to discover dynamic partitions available
hcatalog/core/src/main/java/org/apache/hive/hcatalog/mapreduce/FileOutputCommitterContainer.java