This is an automated email from the ASF dual-hosted git repository.

andor pushed a commit to branch HBASE-29081
in repository https://gitbox.apache.org/repos/asf/hbase.git

commit a43467dc850129624ad3a9203f0b4fa5bc20acbd
Author: Andor Molnár <[email protected]>
AuthorDate: Wed Apr 8 06:49:07 2026 -0700

    HBASE-29993. Refactor ClusterId/ActiveClusterSuffix reading and writing in 
FSUtils (#8006)
    
    * HBASE-29993. Refactor cluster id and suffix in FSUtils
    
    * HBASE-29993. Spotless apply
    
    * HBASE-29993. Renaming
    
    * Fix typo
    
    Co-authored-by: Kevin Geiszler <[email protected]>
    
    * HBASE-29993. Spotless apply
    
    ---------
    
    Co-authored-by: Kevin Geiszler <[email protected]>
---
 .../apache/hadoop/hbase/ActiveClusterSuffix.java   |  75 ++++++-----
 .../java/org/apache/hadoop/hbase/ClusterId.java    |  64 ++++++----
 .../org/apache/hadoop/hbase/ClusterIdFile.java     |  34 +++++
 .../apache/hadoop/hbase/ClusterIdFileParser.java   |  48 +++++++
 .../hadoop/hbase/client/ZKConnectionRegistry.java  |   2 +-
 .../hadoop/hbase/master/CachedClusterId.java       |   2 +-
 .../hadoop/hbase/master/MasterFileSystem.java      |  15 ++-
 .../access/AbstractReadOnlyController.java         |   3 +-
 .../java/org/apache/hadoop/hbase/util/FSUtils.java | 138 +++++----------------
 .../apache/hadoop/hbase/zookeeper/ZKClusterId.java |   2 +-
 10 files changed, 217 insertions(+), 166 deletions(-)

diff --git 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/ActiveClusterSuffix.java 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/ActiveClusterSuffix.java
index 4d3409a1211..2864c456755 100644
--- 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/ActiveClusterSuffix.java
+++ 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/ActiveClusterSuffix.java
@@ -30,14 +30,54 @@ import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
 import 
org.apache.hadoop.hbase.shaded.protobuf.generated.ActiveClusterSuffixProtos;
 
 /**
- * The suffix for this cluster. It is serialized to the filesystem and up into 
zookeeper. This is a
- * container for the id. Also knows how to serialize and deserialize the 
cluster id.
+ * The read-replica cluster id for this cluster. It is serialized to the 
filesystem and up into
+ * zookeeper. This is a container for the id. Also knows how to serialize and 
deserialize the
+ * cluster id.
  */
 @InterfaceAudience.Private
-public class ActiveClusterSuffix {
+public class ActiveClusterSuffix implements ClusterIdFile {
   private final String cluster_id;
   private final String suffix;
 
+  public static class Parser implements 
ClusterIdFileParser<ActiveClusterSuffix> {
+
+    @Override
+    public String getFileName() {
+      return HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME;
+    }
+
+    /**
+     * Parse the serialized representation of the {@link ActiveClusterSuffix}
+     * @param bytes A pb serialized {@link ActiveClusterSuffix} instance with 
pb magic prefix
+     * @return An instance of {@link ActiveClusterSuffix} made from 
<code>bytes</code>
+     * @see #toByteArray()
+     */
+    @Override
+    public ActiveClusterSuffix parseFrom(byte[] bytes) throws 
DeserializationException {
+      if (ProtobufUtil.isPBMagicPrefix(bytes)) {
+        int pblen = ProtobufUtil.lengthOfPBMagic();
+        ActiveClusterSuffixProtos.ActiveClusterSuffix.Builder builder =
+          ActiveClusterSuffixProtos.ActiveClusterSuffix.newBuilder();
+        ActiveClusterSuffixProtos.ActiveClusterSuffix cs = null;
+        try {
+          ProtobufUtil.mergeFrom(builder, bytes, pblen, bytes.length - pblen);
+          cs = builder.build();
+        } catch (IOException e) {
+          throw new DeserializationException(e);
+        }
+        return convert(cs);
+      } else {
+        // Presume it was written out this way, the old way.
+        return new ActiveClusterSuffix(Bytes.toString(bytes));
+      }
+    }
+
+    @Override
+    public ActiveClusterSuffix readString(String input) {
+      return new ActiveClusterSuffix(input);
+    }
+  }
+
   public ActiveClusterSuffix(final String ci, final String suffix) {
     this.cluster_id = ci;
     this.suffix = suffix;
@@ -53,6 +93,10 @@ public class ActiveClusterSuffix {
     }
   }
 
+  public static ActiveClusterSuffix parseFrom(byte[] bytes) throws 
DeserializationException {
+    return new Parser().parseFrom(bytes);
+  }
+
   public static ActiveClusterSuffix fromConfig(Configuration conf, ClusterId 
clusterId) {
     return new ActiveClusterSuffix(clusterId.toString(), conf
       .get(HConstants.HBASE_META_TABLE_SUFFIX, 
HConstants.HBASE_META_TABLE_SUFFIX_DEFAULT_VALUE));
@@ -63,31 +107,6 @@ public class ActiveClusterSuffix {
     return ProtobufUtil.prependPBMagic(convert().toByteArray());
   }
 
-  /**
-   * Parse the serialized representation of the {@link ActiveClusterSuffix}
-   * @param bytes A pb serialized {@link ActiveClusterSuffix} instance with pb 
magic prefix
-   * @return An instance of {@link ActiveClusterSuffix} made from 
<code>bytes</code>
-   * @see #toByteArray()
-   */
-  public static ActiveClusterSuffix parseFrom(final byte[] bytes) throws 
DeserializationException {
-    if (ProtobufUtil.isPBMagicPrefix(bytes)) {
-      int pblen = ProtobufUtil.lengthOfPBMagic();
-      ActiveClusterSuffixProtos.ActiveClusterSuffix.Builder builder =
-        ActiveClusterSuffixProtos.ActiveClusterSuffix.newBuilder();
-      ActiveClusterSuffixProtos.ActiveClusterSuffix cs = null;
-      try {
-        ProtobufUtil.mergeFrom(builder, bytes, pblen, bytes.length - pblen);
-        cs = builder.build();
-      } catch (IOException e) {
-        throw new DeserializationException(e);
-      }
-      return convert(cs);
-    } else {
-      // Presume it was written out this way, the old way.
-      return new ActiveClusterSuffix(Bytes.toString(bytes));
-    }
-  }
-
   /** Returns A pb instance to represent this instance. */
   public ActiveClusterSuffixProtos.ActiveClusterSuffix convert() {
     return 
ActiveClusterSuffixProtos.ActiveClusterSuffix.newBuilder().setClusterId(cluster_id)
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/ClusterId.java 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/ClusterId.java
index 67438677dad..19a2e95dbd8 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/ClusterId.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/ClusterId.java
@@ -31,9 +31,47 @@ import 
org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterIdProtos;
  * is a container for the id. Also knows how to serialize and deserialize the 
cluster id.
  */
 @InterfaceAudience.Private
-public class ClusterId {
+public class ClusterId implements ClusterIdFile {
   private final String id;
 
+  public static class Parser implements ClusterIdFileParser<ClusterId> {
+
+    @Override
+    public String getFileName() {
+      return HConstants.CLUSTER_ID_FILE_NAME;
+    }
+
+    /**
+     * Parse the serialized representation of the {@link ClusterId}
+     * @param bytes A pb serialized {@link ClusterId} instance with pb magic 
prefix
+     * @return An instance of {@link ClusterId} made from <code>bytes</code>
+     * @see #toByteArray()
+     */
+    @Override
+    public ClusterId parseFrom(byte[] bytes) throws DeserializationException {
+      if (ProtobufUtil.isPBMagicPrefix(bytes)) {
+        int pblen = ProtobufUtil.lengthOfPBMagic();
+        ClusterIdProtos.ClusterId.Builder builder = 
ClusterIdProtos.ClusterId.newBuilder();
+        ClusterIdProtos.ClusterId cid = null;
+        try {
+          ProtobufUtil.mergeFrom(builder, bytes, pblen, bytes.length - pblen);
+          cid = builder.build();
+        } catch (IOException e) {
+          throw new DeserializationException(e);
+        }
+        return convert(cid);
+      } else {
+        // Presume it was written out this way, the old way.
+        return new ClusterId(Bytes.toString(bytes));
+      }
+    }
+
+    @Override
+    public ClusterId readString(String input) {
+      return new ClusterId(input);
+    }
+  }
+
   /**
    * New ClusterID. Generates a uniqueid.
    */
@@ -50,30 +88,6 @@ public class ClusterId {
     return ProtobufUtil.prependPBMagic(convert().toByteArray());
   }
 
-  /**
-   * Parse the serialized representation of the {@link ClusterId}
-   * @param bytes A pb serialized {@link ClusterId} instance with pb magic 
prefix
-   * @return An instance of {@link ClusterId} made from <code>bytes</code>
-   * @see #toByteArray()
-   */
-  public static ClusterId parseFrom(final byte[] bytes) throws 
DeserializationException {
-    if (ProtobufUtil.isPBMagicPrefix(bytes)) {
-      int pblen = ProtobufUtil.lengthOfPBMagic();
-      ClusterIdProtos.ClusterId.Builder builder = 
ClusterIdProtos.ClusterId.newBuilder();
-      ClusterIdProtos.ClusterId cid = null;
-      try {
-        ProtobufUtil.mergeFrom(builder, bytes, pblen, bytes.length - pblen);
-        cid = builder.build();
-      } catch (IOException e) {
-        throw new DeserializationException(e);
-      }
-      return convert(cid);
-    } else {
-      // Presume it was written out this way, the old way.
-      return new ClusterId(Bytes.toString(bytes));
-    }
-  }
-
   /** Returns A pb instance to represent this instance. */
   public ClusterIdProtos.ClusterId convert() {
     ClusterIdProtos.ClusterId.Builder builder = 
ClusterIdProtos.ClusterId.newBuilder();
diff --git 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/ClusterIdFile.java 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/ClusterIdFile.java
new file mode 100644
index 00000000000..8b3aec7d552
--- /dev/null
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/ClusterIdFile.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase;
+
+import org.apache.yetus.audience.InterfaceAudience;
+
+/**
+ * Represents a cluster identification file on the master file system. e.g. 
Cluster ID = hbase.id
+ * Active read-replica cluster ID = active.cluster.suffix.id
+ */
[email protected]
+public interface ClusterIdFile {
+
+  /**
+   * Return file contents in a byte array.
+   */
+  byte[] toByteArray();
+
+}
diff --git 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/ClusterIdFileParser.java 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/ClusterIdFileParser.java
new file mode 100644
index 00000000000..39f34bdac94
--- /dev/null
+++ 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/ClusterIdFileParser.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase;
+
+import org.apache.hadoop.hbase.exceptions.DeserializationException;
+import org.apache.yetus.audience.InterfaceAudience;
+
+/**
+ * Generic parser interface for Cluster Id files.
+ * @see ClusterIdFile
+ */
[email protected]
+public interface ClusterIdFileParser<T> {
+
+  /**
+   * Get default file name of cluster id file.
+   */
+  String getFileName();
+
+  /**
+   * Parse cluster id data from byte representation.
+   * @param bytes the protobuf data
+   * @return the cluster id data object
+   */
+  T parseFrom(final byte[] bytes) throws DeserializationException;
+
+  /**
+   * Parser cluster id data from String representation.
+   * @param input the input string
+   * @return the cluster id data object
+   */
+  T readString(String input);
+}
diff --git 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ZKConnectionRegistry.java
 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ZKConnectionRegistry.java
index d31c0090f56..40ecc7694ca 100644
--- 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ZKConnectionRegistry.java
+++ 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ZKConnectionRegistry.java
@@ -117,7 +117,7 @@ class ZKConnectionRegistry implements ConnectionRegistry {
       return null;
     }
     data = removeMetaData(data);
-    return ClusterId.parseFrom(data).toString();
+    return new ClusterId.Parser().parseFrom(data).toString();
   }
 
   @Override
diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/CachedClusterId.java
 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/CachedClusterId.java
index 67d8ef80ce6..9cb2138642c 100644
--- 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/CachedClusterId.java
+++ 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/CachedClusterId.java
@@ -102,7 +102,7 @@ public class CachedClusterId {
       // the waiting threads.
       try {
         cacheMisses.incrementAndGet();
-        setClusterId(FSUtils.getClusterId(fs, rootDir));
+        setClusterId(FSUtils.getClusterIdFile(fs, rootDir, new 
ClusterId.Parser()));
       } catch (IOException e) {
         LOG.warn("Error fetching cluster ID", e);
       } finally {
diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterFileSystem.java
 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterFileSystem.java
index 3708e28e5fd..95c31fb9776 100644
--- 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterFileSystem.java
+++ 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterFileSystem.java
@@ -271,9 +271,10 @@ public class MasterFileSystem {
       !FSUtils.checkFileExistsInHbaseRootDir(fs, rootdir, 
HConstants.CLUSTER_ID_FILE_NAME,
         threadWakeFrequency)
     ) {
-      FSUtils.setClusterId(fs, rootdir, new ClusterId(), threadWakeFrequency);
+      FSUtils.setClusterIdFile(fs, rootdir, HConstants.CLUSTER_ID_FILE_NAME, 
new ClusterId(),
+        threadWakeFrequency);
     }
-    clusterId = FSUtils.getClusterId(fs, rootdir);
+    clusterId = FSUtils.getClusterIdFile(fs, rootdir, new ClusterId.Parser());
     negotiateActiveClusterSuffixFile(threadWakeFrequency);
   }
 
@@ -397,7 +398,12 @@ public class MasterFileSystem {
     if (!isReadOnlyModeEnabled(conf)) {
       try {
         // verify the contents against the config set
-        ActiveClusterSuffix acs = FSUtils.getActiveClusterSuffix(fs, rootdir);
+        ActiveClusterSuffix acs =
+          FSUtils.getClusterIdFile(fs, rootdir, new 
ActiveClusterSuffix.Parser());
+        if (acs == null) {
+          throw new FileNotFoundException("[Read-replica feature] Active 
Cluster Suffix File "
+            + new Path(rootdir, HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME) + 
" not found");
+        }
         LOG.debug(
           "Negotiating active cluster suffix file. File {} : File Suffix {} : 
Configured suffix {} :  Cluster ID : {}",
           new Path(rootdir, HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME), acs, 
activeClusterSuffix,
@@ -418,7 +424,8 @@ public class MasterFileSystem {
           activeClusterSuffix);
       } catch (FileNotFoundException fnfe) {
         // We're in read/write mode, but suffix file missing, let's create it
-        FSUtils.setActiveClusterSuffix(fs, rootdir, activeClusterSuffix, wait);
+        FSUtils.setClusterIdFile(fs, rootdir, 
HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME,
+          activeClusterSuffix, wait);
         LOG.info("[Read-replica feature] Created Active cluster suffix file: 
{}, with content: {}",
           HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME, activeClusterSuffix);
       }
diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AbstractReadOnlyController.java
 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AbstractReadOnlyController.java
index b157adf72c9..c82f0b10aa1 100644
--- 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AbstractReadOnlyController.java
+++ 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AbstractReadOnlyController.java
@@ -107,7 +107,8 @@ public abstract class AbstractReadOnlyController implements 
Coprocessor {
         // DISABLING READ-ONLY (true -> false), create the active cluster file 
id file
         int wait = 
mfs.getConfiguration().getInt(HConstants.THREAD_WAKE_FREQUENCY, 10 * 1000);
         if (!fs.exists(activeClusterFile)) {
-          FSUtils.setActiveClusterSuffix(fs, rootDir, 
mfs.getActiveClusterSuffix(), wait);
+          FSUtils.setClusterIdFile(fs, rootDir, 
HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME,
+            mfs.getActiveClusterSuffix(), wait);
         } else {
           LOG.debug("Active cluster file already exists at: {}. No need to 
create it again.",
             activeClusterFile);
diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java
index 0fbd07eaa0b..40c084cbac8 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java
@@ -65,8 +65,8 @@ import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.PathFilter;
 import org.apache.hadoop.fs.StorageType;
 import org.apache.hadoop.fs.permission.FsPermission;
-import org.apache.hadoop.hbase.ActiveClusterSuffix;
-import org.apache.hadoop.hbase.ClusterId;
+import org.apache.hadoop.hbase.ClusterIdFile;
+import org.apache.hadoop.hbase.ClusterIdFileParser;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HDFSBlocksDistribution;
 import org.apache.hadoop.hbase.TableName;
@@ -565,15 +565,13 @@ public final class FSUtils {
   }
 
   /**
-   * Returns the value of the unique cluster ID stored for this HBase instance.
-   * @param fs      the root directory FileSystem
-   * @param rootdir the path to the HBase root directory
-   * @return the unique cluster identifier
-   * @throws IOException if reading the cluster ID file fails
+   * Use the given parser object to read and parse contents of Cluster Id 
file. e.g. Cluster Id or
+   * Active read-replica Cluster Id
    */
-  public static ClusterId getClusterId(FileSystem fs, Path rootdir) throws 
IOException {
-    Path idPath = new Path(rootdir, HConstants.CLUSTER_ID_FILE_NAME);
-    ClusterId clusterId = null;
+  public static <T extends ClusterIdFile> T getClusterIdFile(FileSystem fs, 
Path rootdir,
+    ClusterIdFileParser<T> parser) throws IOException {
+    Path idPath = new Path(rootdir, parser.getFileName());
+    T cs = null;
     FileStatus status = fs.exists(idPath) ? fs.getFileStatus(idPath) : null;
     if (status != null) {
       int len = Ints.checkedCast(status.getLen());
@@ -582,12 +580,12 @@ public final class FSUtils {
       try {
         in.readFully(content);
       } catch (EOFException eof) {
-        LOG.warn("Cluster ID file {} is empty", idPath);
+        LOG.warn("Cluster file {} is empty", idPath);
       } finally {
         in.close();
       }
       try {
-        clusterId = ClusterId.parseFrom(content);
+        cs = parser.parseFrom(content);
       } catch (DeserializationException e) {
         throw new IOException("content=" + Bytes.toString(content), e);
       }
@@ -597,122 +595,53 @@ public final class FSUtils {
         in = fs.open(idPath);
         try {
           cid = in.readUTF();
-          clusterId = new ClusterId(cid);
-        } catch (EOFException eof) {
-          LOG.warn("Cluster ID file {} is empty", idPath);
-        } finally {
-          in.close();
-        }
-        rewriteAsPb(fs, rootdir, idPath, clusterId);
-      }
-      return clusterId;
-    } else {
-      LOG.warn("Cluster ID file does not exist at {}", idPath);
-    }
-    return clusterId;
-  }
-
-  public static ActiveClusterSuffix getActiveClusterSuffix(FileSystem fs, Path 
rootdir)
-    throws IOException {
-    Path idPath = new Path(rootdir, 
HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME);
-    ActiveClusterSuffix cs = null;
-    FileStatus status = fs.exists(idPath) ? fs.getFileStatus(idPath) : null;
-    if (status != null) {
-      int len = Ints.checkedCast(status.getLen());
-      byte[] content = new byte[len];
-      FSDataInputStream in = fs.open(idPath);
-      try {
-        in.readFully(content);
-      } catch (EOFException eof) {
-        LOG.warn("Cluster Suffix file {} is empty   ", idPath);
-      } finally {
-        in.close();
-      }
-      try {
-        cs = ActiveClusterSuffix.parseFrom(content);
-      } catch (DeserializationException e) {
-        throw new IOException("content=" + Bytes.toString(content), e);
-      }
-      // If not pb'd, make it so.
-      if (!ProtobufUtil.isPBMagicPrefix(content)) {
-        String data = null;
-        in = fs.open(idPath);
-        try {
-          data = in.readUTF();
-          cs = new ActiveClusterSuffix(data);
+          cs = parser.readString(cid);
         } catch (EOFException eof) {
-          LOG.warn("[Read-replica Feature] Active Cluster id file {} is empty 
", idPath);
+          LOG.warn("Cluster file {} is empty", idPath);
         } finally {
           in.close();
         }
-        rewriteAsPb(fs, rootdir, idPath, cs);
+        rewriteAsPb(fs, rootdir, idPath, parser.getFileName(), cs);
       }
       return cs;
     } else {
-      throw new FileNotFoundException(
-        "[Read-replica feature] Active Cluster Suffix File " + idPath + " not 
found");
+      LOG.warn("Cluster file does not exist at {}", idPath);
     }
+    return cs;
   }
 
-  private static void rewriteAsPb(final FileSystem fs, final Path rootdir, 
final Path p,
-    final ClusterId cid) throws IOException {
+  private static <T extends ClusterIdFile> void rewriteAsPb(final FileSystem 
fs, final Path rootdir,
+    final Path p, final String fileName, final T cs) throws IOException {
     // Rewrite the file as pb. Move aside the old one first, write new
     // then delete the moved-aside file.
     Path movedAsideName = new Path(p + "." + 
EnvironmentEdgeManager.currentTime());
     if (!fs.rename(p, movedAsideName)) throw new IOException("Failed rename of 
" + p);
-    setClusterId(fs, rootdir, cid, 100);
+    setClusterIdFile(fs, rootdir, fileName, cs, 100);
     if (!fs.delete(movedAsideName, false)) {
       throw new IOException("Failed delete of " + movedAsideName);
     }
-    LOG.debug("Rewrote the hbase.id file as pb");
-  }
-
-  private static void rewriteAsPb(final FileSystem fs, final Path rootdir, 
final Path p,
-    final ActiveClusterSuffix cs) throws IOException {
-    // Rewrite the file as pb. Move aside the old one first, write new
-    // then delete the moved-aside file.
-    Path movedAsideName = new Path(p + "." + 
EnvironmentEdgeManager.currentTime());
-    if (!fs.rename(p, movedAsideName)) throw new IOException("Failed rename of 
" + p);
-    setActiveClusterSuffix(fs, rootdir, cs, 100);
-    if (!fs.delete(movedAsideName, false)) {
-      throw new IOException("Failed delete of " + movedAsideName);
-    }
-    LOG.debug("Rewrote the active.cluster.suffix.id file as pb");
+    LOG.debug("Rewrote the {} file as pb", fileName);
   }
 
   /**
-   * Writes a new unique identifier for this cluster to the "hbase.id" file in 
the HBase root
-   * directory. If any operations on the ID file fails, and {@code wait} is a 
positive value, the
-   * method will retry to produce the ID file until the thread is forcibly 
interrupted.
-   * @param fs        the root directory FileSystem
-   * @param rootdir   the path to the HBase root directory
-   * @param clusterId the unique identifier to store
-   * @param wait      how long (in milliseconds) to wait between retries
+   * Writes a new unique identifier for this cluster to the Cluster Id 
("hbase.id" or
+   * "active.cluster.suffix.id") file in the HBase root directory. If any 
operations on the ID file
+   * fails, and {@code wait} is a positive value, the method will retry to 
produce the ID file until
+   * the thread is forcibly interrupted.
+   * @param fs       the root directory FileSystem
+   * @param rootdir  the path to the HBase root directory
+   * @param fileName name of the file to be written
+   * @param cs       the object to be written
+   * @param wait     how long (in milliseconds) to wait between retries
    * @throws IOException if writing to the FileSystem fails and no wait value
    */
-  public static void setClusterId(final FileSystem fs, final Path rootdir,
-    final ClusterId clusterId, final long wait) throws IOException {
-    final Path idFile = new Path(rootdir, HConstants.CLUSTER_ID_FILE_NAME);
+  public static <T extends ClusterIdFile> void setClusterIdFile(final 
FileSystem fs,
+    final Path rootdir, final String fileName, final T cs, final long wait) 
throws IOException {
+    final Path idFile = new Path(rootdir, fileName);
     final Path tempDir = new Path(rootdir, HConstants.HBASE_TEMP_DIRECTORY);
-    final Path tempIdFile = new Path(tempDir, HConstants.CLUSTER_ID_FILE_NAME);
-
-    LOG.debug("Create cluster ID file [{}] with ID: {}", idFile, clusterId);
-    writeClusterInfo(fs, rootdir, idFile, tempIdFile, clusterId.toByteArray(), 
wait);
-  }
+    final Path tempIdFile = new Path(tempDir, fileName);
 
-  /**
-   * Writes a user provided suffix for this cluster to the 
"active_cluster_suffix.id" file in the
-   * HBase root directory. If any operations on the ID file fails, and {@code 
wait} is a positive
-   * value, the method will retry to produce the ID file until the thread is 
forcibly interrupted.
-   */
-  public static void setActiveClusterSuffix(final FileSystem fs, final Path 
rootdir,
-    final ActiveClusterSuffix cs, final long wait) throws IOException {
-    final Path idFile = new Path(rootdir, 
HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME);
-    final Path tempDir = new Path(rootdir, HConstants.HBASE_TEMP_DIRECTORY);
-    final Path tempIdFile = new Path(tempDir, 
HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME);
-
-    LOG.debug("[Read-replica feature] id file [{}] is present and contains 
cluster id: {}", idFile,
-      cs);
+    LOG.debug("Cluster file [{}] is present and contains cluster id: {}", 
idFile, cs);
     writeClusterInfo(fs, rootdir, idFile, tempIdFile, cs.toByteArray(), wait);
   }
 
@@ -723,7 +652,6 @@ public final class FSUtils {
    * {@code wait} is a positive value, the method will retry to produce the ID 
file until the thread
    * is forcibly interrupted.
    */
-
   private static void writeClusterInfo(final FileSystem fs, final Path 
rootdir, final Path idFile,
     final Path tempIdFile, byte[] fileData, final long wait) throws 
IOException {
     while (true) {
diff --git 
a/hbase-zookeeper/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKClusterId.java
 
b/hbase-zookeeper/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKClusterId.java
index 71d8f87bbc2..4eea7d66de0 100644
--- 
a/hbase-zookeeper/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKClusterId.java
+++ 
b/hbase-zookeeper/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKClusterId.java
@@ -66,7 +66,7 @@ public class ZKClusterId {
       }
       if (data != null) {
         try {
-          return ClusterId.parseFrom(data).toString();
+          return new ClusterId.Parser().parseFrom(data).toString();
         } catch (DeserializationException e) {
           throw ZKUtil.convert(e);
         }

Reply via email to