Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -358,4 +358,23 @@ public long getDeletionMs() {
public static void setDeletionMs(long 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,58 @@ public void testRegistrationMajorityQuorum()
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
public void testRegistrationQuorumExcludesExpired()
throws InterruptedException, IOException {
Expand Down