/**
   * Action before any real action of modifying column family.
   *
   * @param env MasterProcedureEnv
   * @throws IOException
   */
  private void prepareModify(final MasterProcedureEnv env) throws IOException {
    // Checks whether the table is allowed to be modified.
    MasterDDLOperationHelper.checkTableModifiable(env, tableName);

    unmodifiedHTableDescriptor = env.getMasterServices().getTableDescriptors().get(tableName);
    if (unmodifiedHTableDescriptor == null) {
      throw new IOException("HTableDescriptor missing for " + tableName);
    }
    if (!unmodifiedHTableDescriptor.hasFamily(cfDescriptor.getName())) {
      throw new InvalidFamilyOperationException(
          "Family '" + getColumnFamilyName() + "' does not exist, so it cannot be modified");
    }
  }
  /**
   * Last action from the procedure - executed when online schema change is supported.
   *
   * @param env MasterProcedureEnv
   * @throws IOException
   */
  private void reOpenAllRegionsIfTableIsOnline(final MasterProcedureEnv env) throws IOException {
    // This operation only run when the table is enabled.
    if (!env.getMasterServices()
        .getAssignmentManager()
        .getTableStateManager()
        .isTableState(getTableName(), TableState.State.ENABLED)) {
      return;
    }

    if (MasterDDLOperationHelper.reOpenAllRegions(env, getTableName(), getRegionInfoList(env))) {
      LOG.info("Completed add column family operation on table " + getTableName());
    } else {
      LOG.warn("Error on reopening the regions on table " + getTableName());
    }
  }
  /**
   * Restore the table descriptor back to pre-add
   *
   * @param env MasterProcedureEnv
   * @throws IOException
   */
  private void restoreTableDescriptor(final MasterProcedureEnv env) throws IOException {
    HTableDescriptor htd = env.getMasterServices().getTableDescriptors().get(tableName);
    if (htd.hasFamily(cfDescriptor.getName())) {
      // Remove the column family from file system and update the table descriptor to
      // the before-add-column-family-state
      MasterDDLOperationHelper.deleteColumnFamilyFromFileSystem(
          env,
          tableName,
          getRegionInfoList(env),
          cfDescriptor.getName(),
          cfDescriptor.isMobEnabled());

      env.getMasterServices().getTableDescriptors().add(unmodifiedHTableDescriptor);

      // Make sure regions are opened after table descriptor is updated.
      reOpenAllRegionsIfTableIsOnline(env);
    }
  }
  /**
   * Action before any real action of adding column family.
   *
   * @param env MasterProcedureEnv
   * @throws IOException
   */
  private void prepareAdd(final MasterProcedureEnv env) throws IOException {
    // Checks whether the table is allowed to be modified.
    MasterDDLOperationHelper.checkTableModifiable(env, tableName);

    // In order to update the descriptor, we need to retrieve the old descriptor for comparison.
    unmodifiedHTableDescriptor = env.getMasterServices().getTableDescriptors().get(tableName);
    if (unmodifiedHTableDescriptor == null) {
      throw new IOException("HTableDescriptor missing for " + tableName);
    }
    if (unmodifiedHTableDescriptor.hasFamily(cfDescriptor.getName())) {
      throw new InvalidFamilyOperationException(
          "Column family '"
              + getColumnFamilyName()
              + "' in table '"
              + tableName
              + "' already exists so cannot be added");
    }
  }