anmolnar commented on code in PR #6887:
URL: https://github.com/apache/hbase/pull/6887#discussion_r2069040971


##########
hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterFileSystem.java:
##########
@@ -382,4 +394,61 @@ public void stop() {
   public void logFileSystemState(Logger log) throws IOException {
     CommonFSUtils.logFileSystemState(fs, rootdir, log);
   }
+
+  private void negotiateActiveClusterSuffixFile(long wait) throws IOException {
+    LOG.info("Active cluster Suffix file");

Review Comment:
   Please remove this log line. It doesn't add value.



##########
hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterFileSystem.java:
##########
@@ -382,4 +394,61 @@ public void stop() {
   public void logFileSystemState(Logger log) throws IOException {
     CommonFSUtils.logFileSystemState(fs, rootdir, log);
   }
+
+  private void negotiateActiveClusterSuffixFile(long wait) throws IOException {
+    LOG.info("Active cluster Suffix file");
+    String suffix_file_name = HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME;
+    boolean activeClusterSuffixFileExists =
+      FSUtils.checkFileExistsInHbaseRootDir(fs, rootdir, suffix_file_name, 
wait);
+
+    if (!isReadOnlyModeEnabled(conf)) {
+      // this is the active cluster, create active cluster suffix file if it 
does not exist
+      if (!activeClusterSuffixFileExists) {
+        FSUtils.setActiveClusterSuffix(fs, rootdir, 
getSuffixFileDataToWrite(), wait);
+      } else {
+        // verify the contents against the config set
+        ActiveClusterSuffix acs = FSUtils.getActiveClusterSuffix(fs, rootdir);
+        if (Objects.equals(acs.getActiveClusterSuffix(), 
getActiveClusterSuffix())) {
+          LOG.info("This is the active cluster on this storage location, "
+            + "File Suffix {} : Suffix {} : ", acs, getActiveClusterSuffix());

Review Comment:
   Move this log entry one level up when the else branch is finished without 
error. Either we created a new active_cluster file or verified the contents of 
the existing, we're good to continue as the only active cluster.



##########
hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java:
##########
@@ -857,6 +935,12 @@ public static void renameFile(FileSystem fs, Path src, 
Path dst) throws IOExcept
     }
   }
 
+  public static void removeFile(FileSystem fs, Path filepath) throws 
IOException {

Review Comment:
   This method is not used.



##########
hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterFileSystem.java:
##########
@@ -382,4 +394,61 @@ public void stop() {
   public void logFileSystemState(Logger log) throws IOException {
     CommonFSUtils.logFileSystemState(fs, rootdir, log);
   }
+
+  private void negotiateActiveClusterSuffixFile(long wait) throws IOException {
+    LOG.info("Active cluster Suffix file");
+    String suffix_file_name = HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME;
+    boolean activeClusterSuffixFileExists =
+      FSUtils.checkFileExistsInHbaseRootDir(fs, rootdir, suffix_file_name, 
wait);
+
+    if (!isReadOnlyModeEnabled(conf)) {
+      // this is the active cluster, create active cluster suffix file if it 
does not exist
+      if (!activeClusterSuffixFileExists) {
+        FSUtils.setActiveClusterSuffix(fs, rootdir, 
getSuffixFileDataToWrite(), wait);
+      } else {
+        // verify the contents against the config set
+        ActiveClusterSuffix acs = FSUtils.getActiveClusterSuffix(fs, rootdir);
+        if (Objects.equals(acs.getActiveClusterSuffix(), 
getActiveClusterSuffix())) {
+          LOG.info("This is the active cluster on this storage location, "
+            + "File Suffix {} : Suffix {} : ", acs, getActiveClusterSuffix());
+        } else {
+          // throw error
+          LOG.info("rootdir {} : Active Cluster File Suffix {} ", rootdir, 
acs);
+          throw new IOException("Can not start active cluster, please check 
the value of "
+            + "configuration hbase.global.readonly.enabled in hbase-site.xml, "
+            + "Active Cluster Suffix : " + getActiveClusterSuffix()
+            + ": Active Cluster File Suffix " + acs);

Review Comment:
   Please rephrase the error message something like:
   > Cannot start master, because another cluster is running in active 
(read-write) mode on this storage location. Active Cluster Id: ...  This 
cluster Id: ...



##########
hbase-server/src/main/java/org/apache/hadoop/hbase/util/FSUtils.java:
##########
@@ -612,31 +668,54 @@ private static void rewriteAsPb(final FileSystem fs, 
final Path rootdir, final P
    */
   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);
     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);
+  }
+
+  /**
+   * 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, byte[] bdata,
+    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);
+    writeClusterInfo(fs, rootdir, idFile, tempIdFile, bdata, wait);

Review Comment:
   The method which creates the ClusterId file has a debug level log message 
here. I think it would be useful to copy that here too.



##########
hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestActiveClusterSuffix.java:
##########
@@ -0,0 +1,133 @@
+/*
+ * 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.regionserver;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import org.apache.hadoop.fs.FSDataOutputStream;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.HBaseClassTestRule;
+import org.apache.hadoop.hbase.HBaseTestingUtil;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.master.MasterFileSystem;
+import org.apache.hadoop.hbase.testclassification.MediumTests;
+import org.apache.hadoop.hbase.testclassification.RegionServerTests;
+import org.apache.hadoop.hbase.util.CommonFSUtils;
+import org.apache.hadoop.hbase.util.JVMClusterUtil;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+/**
+ * Test Active Cluster Suffix file.
+ */
+@Category({ RegionServerTests.class, MediumTests.class })
+public class TestActiveClusterSuffix {
+
+  @ClassRule
+  public static final HBaseClassTestRule CLASS_RULE =
+    HBaseClassTestRule.forClass(TestActiveClusterSuffix.class);
+
+  private final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
+
+  private JVMClusterUtil.RegionServerThread rst;
+
+  @Before
+  public void setUp() throws Exception {
+    TEST_UTIL.getConfiguration().setBoolean(ShutdownHook.RUN_SHUTDOWN_HOOK, 
false);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    TEST_UTIL.shutdownMiniCluster();
+    if (rst != null && rst.getRegionServer() != null) {
+      rst.getRegionServer().stop("end of test");
+      rst.join();
+    }
+  }
+
+  @Test
+  public void testActiveClusterSuffixCreated() throws Exception {
+    TEST_UTIL.startMiniZKCluster();
+    TEST_UTIL.startMiniDFSCluster(1);
+    TEST_UTIL.createRootDir();
+    TEST_UTIL.startMiniHBaseCluster();
+    Path rootDir = CommonFSUtils.getRootDir(TEST_UTIL.getConfiguration());
+    FileSystem fs = rootDir.getFileSystem(TEST_UTIL.getConfiguration());
+    Path filePath = new Path(rootDir, 
HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME);
+
+    assertTrue(filePath + " should exists ", fs.exists(filePath));
+    assertTrue(filePath + " should not be empty  ", 
fs.getFileStatus(filePath).getLen() > 0);
+  }
+
+  @Test
+  public void testSuffixFileOnRestart() throws Exception {
+    TEST_UTIL.startMiniZKCluster();
+    TEST_UTIL.startMiniDFSCluster(1);
+    TEST_UTIL.createRootDir();
+    TEST_UTIL.startMiniHBaseCluster();
+    Path rootDir = CommonFSUtils.getRootDir(TEST_UTIL.getConfiguration());
+    FileSystem fs = rootDir.getFileSystem(TEST_UTIL.getConfiguration());
+    Path filePath = new Path(rootDir, 
HConstants.ACTIVE_CLUSTER_SUFFIX_FILE_NAME);
+    assertTrue(filePath + " should exists ", fs.exists(filePath));
+
+    MasterFileSystem mfs = 
TEST_UTIL.getHBaseCluster().getMaster().getMasterFileSystem();
+    // Compute string using currently set suffix and the cluster id
+    String cluster_suffix1 =
+      new String(mfs.getSuffixFileDataToCompare(), StandardCharsets.US_ASCII);
+    // Compute string member variable
+    String cluster_suffix2 = mfs.getActiveClusterSuffix().toString();
+    assertEquals(cluster_suffix1, cluster_suffix2);
+  }
+
+  @Test
+  public void testVerifyErrorWhenSuffixNotMatched() throws Exception {
+    TEST_UTIL.startMiniZKCluster();
+    TEST_UTIL.startMiniDFSCluster(1);
+    TEST_UTIL.createRootDir();
+    Path rootDir = CommonFSUtils.getRootDir(TEST_UTIL.getConfiguration());

Review Comment:
   This test is running for 30+ sec, because that's the default timeout for the 
Master to become active. You can set the following to fail faster:
   ```java
   conf.setInt("hbase.master.start.timeout.localHBaseCluster", 10000);
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to