浏览代码

HDFS-17198. RBF: fix bug of getRepresentativeQuorum when records have same dateModified (#6096)

Jian Zhang 1 年之前
父节点
当前提交
d273c13ab5

+ 19 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/MembershipState.java

@@ -358,4 +358,23 @@ public abstract class MembershipState extends BaseRecord
   public static void setDeletionMs(long time) {
   public static void setDeletionMs(long time) {
     MembershipState.deletionMs = time;
     MembershipState.deletionMs = time;
   }
   }
+
+  /**
+   * First use the comparator of the BaseRecord to compare the date modified.
+   * If they are equal, compare their primary keys to ensure that MembershipStates
+   * with the same date modified but reported by different routers will not be judged as equal.
+   *
+   * @param record the MembershipState object to be compared.
+   * @return a negative integer, zero, or a positive integer as this object
+   *         is less than, equal to, or greater than the specified object.
+   */
+  @Override
+  public int compareTo(BaseRecord record) {
+    int order = super.compareTo(record);
+    if (order == 0) {
+      MembershipState other = (MembershipState) record;
+      return this.getPrimaryKey().compareTo(other.getPrimaryKey());
+    }
+    return order;
+  }
 }
 }

+ 52 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/store/TestStateStoreMembershipState.java

@@ -223,6 +223,58 @@ public class TestStateStoreMembershipState extends TestStateStoreBase {
     assertEquals(quorumEntry.getRouterId(), ROUTERS[3]);
     assertEquals(quorumEntry.getRouterId(), ROUTERS[3]);
   }
   }
 
 
+  /**
+   * Fix getRepresentativeQuorum when records have same date modified time.
+   */
+  @Test
+  public void testRegistrationMajorityQuorumEqDateModified()
+      throws IOException {
+
+    // Populate the state store with a set of non-matching elements
+    // 1) ns0:nn0 - Standby (newest)
+    // 2) ns0:nn0 - Active
+    // 3) ns0:nn0 - Active
+    // 4) ns0:nn0 - Active
+    // (2), (3), (4) have the same date modified time
+    // Verify the selected entry is the newest majority opinion (4)
+    String ns = "ns0";
+    String nn = "nn0";
+
+    long dateModified = Time.now();
+    // Active - oldest
+    MembershipState report = createRegistration(
+        ns, nn, ROUTERS[1], FederationNamenodeServiceState.ACTIVE);
+    report.setDateModified(dateModified);
+    assertTrue(namenodeHeartbeat(report));
+
+    // Active - 2nd oldest
+    report = createRegistration(
+        ns, nn, ROUTERS[2], FederationNamenodeServiceState.ACTIVE);
+    report.setDateModified(dateModified);
+    assertTrue(namenodeHeartbeat(report));
+
+    // Active - 3rd oldest
+    report = createRegistration(
+        ns, nn, ROUTERS[3], FederationNamenodeServiceState.ACTIVE);
+    report.setDateModified(dateModified);
+    assertTrue(namenodeHeartbeat(report));
+
+    // standby - newest overall
+    report = createRegistration(
+        ns, nn, ROUTERS[0], FederationNamenodeServiceState.STANDBY);
+    assertTrue(namenodeHeartbeat(report));
+
+    // Load and calculate quorum
+    assertTrue(getStateStore().loadCache(MembershipStore.class, true));
+
+    // Verify quorum entry
+    MembershipState quorumEntry = getNamenodeRegistration(
+        report.getNameserviceId(), report.getNamenodeId());
+    assertNotNull(quorumEntry);
+    // The name node status should be active
+    assertEquals(FederationNamenodeServiceState.ACTIVE, quorumEntry.getState());
+  }
+
   @Test
   @Test
   public void testRegistrationQuorumExcludesExpired()
   public void testRegistrationQuorumExcludesExpired()
       throws InterruptedException, IOException {
       throws InterruptedException, IOException {