Skip to content
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