private void addPartitionsToMetastore(List<Partition> partitions,
                                        boolean resetStatistics, Table tbl,
                                        List<AcidUtils.TableSnapshot> tableSnapshots)
                                        throws HiveException {
    try {
      if (partitions.isEmpty() || tableSnapshots.isEmpty()) {
        return;
      }
      if (LOG.isDebugEnabled()) {
        StringBuffer debugMsg = new StringBuffer("Adding new partitions ");
        partitions.forEach(partition -> debugMsg.append(partition.getSpec() + " "));
        LOG.debug(debugMsg.toString());
      }
      getSynchronizedMSC().add_partitions(partitions.stream().map(Partition::getTPartition)
              .collect(Collectors.toList()));
    } catch(AlreadyExistsException aee) {
      // With multiple users concurrently issuing insert statements on the same partition has
      // a side effect that some queries may not see a partition at the time when they're issued,
      // but will realize the partition is actually there when it is trying to add such partition
      // to the metastore and thus get AlreadyExistsException, because some earlier query just
      // created it (race condition).
      // For example, imagine such a table is created:
      //  create table T (name char(50)) partitioned by (ds string);
      // and the following two queries are launched at the same time, from different sessions:
      //  insert into table T partition (ds) values ('Bob', 'today'); -- creates the partition 'today'
      //  insert into table T partition (ds) values ('Joe', 'today'); -- will fail with AlreadyExistsException
      // In that case, we want to retry with alterPartition.
      LOG.debug("Caught AlreadyExistsException, trying to add partitions one by one.");
      assert partitions.size() == tableSnapshots.size();
      for (int i = 0; i < partitions.size(); i++) {
        addPartitionToMetastore(partitions.get(i), resetStatistics, tbl,
                tableSnapshots.get(i));
      }
    } catch (Exception e) {
      try {
        for (Partition partition : partitions) {
          final FileSystem newPathFileSystem = partition.getPartitionPath().getFileSystem(this.getConf());
          boolean isSkipTrash = MetaStoreUtils.isSkipTrash(tbl.getParameters());
          final FileStatus status = newPathFileSystem.getFileStatus(partition.getPartitionPath());
          Hive.trashFiles(newPathFileSystem, new FileStatus[]{status}, this.getConf(), isSkipTrash);
        }
      } catch (IOException io) {
        LOG.error("Could not delete partition directory contents after failed partition creation: ", io);
      }
      LOG.error("Failed addPartitionsToMetastore", e);
      throw new HiveException(e);
    }
  }
Move files before creating the partition since down stream processes
check for existence of partition in metadata before accessing the data.
If partition is created before data is moved, downstream waiting
processes might move forward with partial data
ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java