private static Path writeTableDescriptor(final FileSystem fs, final TableDescriptor td,
    final Path tableDir, final FileStatus currentDescriptorFile) throws IOException {
    // Here we will write to the final directory directly to avoid renaming as on OSS renaming is
    // not atomic and has performance issue. The reason why we could do this is that, in the below
    // code we will not overwrite existing files, we will write a new file instead. And when
    // loading, we will skip the half written file, please see the code in getTableDescriptorFromFs
    Path tableInfoDir = new Path(tableDir, TABLEINFO_DIR);

    // In proc v2 we have table lock so typically, there will be no concurrent writes. Keep the
    // retry logic here since we may still want to write the table descriptor from for example,
    // HBCK2?
    int currentSequenceId = currentDescriptorFile == null
      ? 0
      : getTableInfoSequenceIdAndFileLength(currentDescriptorFile.getPath()).sequenceId;

    // Put arbitrary upperbound on how often we retry
    int maxAttempts = 10;
    int maxSequenceId = currentSequenceId + maxAttempts;
    byte[] bytes = TableDescriptorBuilder.toByteArray(td);
    for (int newSequenceId = currentSequenceId + 1; newSequenceId
        <= maxSequenceId; newSequenceId++) {
      String fileName = getTableInfoFileName(newSequenceId, bytes);
      Path filePath = new Path(tableInfoDir, fileName);
      try (FSDataOutputStream out = fs.create(filePath, false)) {
        out.write(bytes);
      } catch (FileAlreadyExistsException e) {
        LOG.debug("{} exists; retrying up to {} times", filePath, maxAttempts, e);
        continue;
      } catch (IOException e) {
        LOG.debug("Failed write {}; retrying up to {} times", filePath, maxAttempts, e);
        continue;
      }
      deleteTableDescriptorFiles(fs, tableInfoDir, newSequenceId - 1);
      return filePath;
    }
    return null;
  }
Attempts to write a new table descriptor to the given table's directory. It begins at the
currentSequenceId + 1 and tries 10 times to find a new sequence number not already in use.
<p/>
Removes the current descriptor file if passed in.
@return Descriptor file or null if we failed write.
hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSTableDescriptors.java