use of org.apache.sling.discovery.impl.cluster.voting.VotingView in project sling by apache.
the class HeartbeatHandler method doCheckViewWith.
/** do the established-against-heartbeat view check using the given resourceResolver.
*/
private void doCheckViewWith(final ResourceResolver resourceResolver) throws PersistenceException {
if (votingHandler == null) {
logger.info("doCheckViewWith: votingHandler is null! slingId=" + slingId);
} else {
votingHandler.analyzeVotings(resourceResolver);
try {
votingHandler.cleanupTimedoutVotings(resourceResolver);
} catch (Exception e) {
logger.warn("doCheckViewWith: Exception occurred while cleaning up votings: " + e, e);
}
}
final VotingView winningVoting = VotingHelper.getWinningVoting(resourceResolver, config);
int numOpenNonWinningVotes = VotingHelper.listOpenNonWinningVotings(resourceResolver, config).size();
if (winningVoting != null || (numOpenNonWinningVotes > 0)) {
// then there are votings pending and I shall wait for them to
// settle
// but first: make sure we sent the TOPOLOGY_CHANGING
logger.info("doCheckViewWith: there are pending votings, marking topology as changing...");
invalidateCurrentEstablishedView();
discoveryServiceImpl.handleTopologyChanging();
if (logger.isDebugEnabled()) {
logger.debug("doCheckViewWith: " + numOpenNonWinningVotes + " ongoing votings, no one winning yet - I shall wait for them to settle.");
}
return;
}
final Resource clusterNodesRes = ResourceHelper.getOrCreateResource(resourceResolver, config.getClusterInstancesPath());
final Set<String> liveInstances = ViewHelper.determineLiveInstances(clusterNodesRes, config);
final View establishedView = ViewHelper.getEstablishedView(resourceResolver, config);
lastEstablishedViewId = establishedView == null ? null : establishedView.getResource().getName();
boolean establishedViewMatches;
if (lastEstablishedViewId != null && failedEstablishedViewId != null && lastEstablishedViewId.equals(failedEstablishedViewId)) {
// SLING-5195 : heartbeat-self-check caused this establishedViewId
// to be declared as failed - so we must now cause a new voting
logger.info("doCheckView: current establishedViewId ({}) was declared as failed earlier already.", lastEstablishedViewId);
establishedViewMatches = false;
} else {
if (establishedView == null) {
establishedViewMatches = false;
} else {
String mismatchDetails;
try {
mismatchDetails = establishedView.matches(liveInstances);
} catch (Exception e) {
logger.error("doCheckViewWith: could not compare established view with live ones: " + e, e);
invalidateCurrentEstablishedView();
discoveryServiceImpl.handleTopologyChanging();
return;
}
if (mismatchDetails != null) {
logger.info("doCheckView: established view does not match. (details: " + mismatchDetails + ")");
} else {
logger.debug("doCheckView: established view matches with expected.");
}
establishedViewMatches = mismatchDetails == null;
}
}
if (establishedViewMatches) {
// that's the normal case. the established view matches what we're
// seeing.
// all happy and fine
logger.debug("doCheckViewWith: no pending nor winning votes. view is fine. we're all happy.");
return;
}
// immediately send a TOPOLOGY_CHANGING - could already be sent, but just to be sure
logger.info("doCheckViewWith: no matching established view, marking topology as changing");
invalidateCurrentEstablishedView();
discoveryServiceImpl.handleTopologyChanging();
List<VotingView> myYesVotes = VotingHelper.getYesVotingsOf(resourceResolver, config, slingId);
if (myYesVotes != null && myYesVotes.size() > 0) {
logger.info("doCheckViewWith: I have voted yes (" + myYesVotes.size() + "x)- the vote was not yet promoted but expecting it to be soon. Not voting again in the meantime. My yes vote was for: " + myYesVotes);
return;
}
if (logger.isDebugEnabled()) {
logger.debug("doCheckViewWith: no pending nor winning votes. But: view does not match established or no established yet. Initiating a new voting");
Iterator<String> it = liveInstances.iterator();
while (it.hasNext()) {
logger.debug("doCheckViewWith: one of the live instances is: " + it.next());
}
}
// we seem to be the first to realize that the currently established
// view doesnt match
// the currently live instances.
// initiate a new voting
doStartNewVoting(resourceResolver, liveInstances);
}
use of org.apache.sling.discovery.impl.cluster.voting.VotingView in project sling by apache.
the class HeartbeatTest method testVotingLoop.
/**
* SLING-5027 : test to reproduce the voting loop
* (and verify that it's fixed)
*/
@Test
public void testVotingLoop() throws Throwable {
logger.info("testVotingLoop: creating slowMachine1...");
FullJR2VirtualInstanceBuilder slowBuilder1 = newBuilder();
slowBuilder1.setDebugName("slow1").newRepository("/var/discovery/impl/", true).setConnectorPingTimeout(600).setConnectorPingInterval(999).setMinEventDelay(0);
FullJR2VirtualInstance slowMachine1 = slowBuilder1.fullBuild();
instances.add(slowMachine1);
SimpleTopologyEventListener slowListener1 = new SimpleTopologyEventListener("slow1");
slowMachine1.bindTopologyEventListener(slowListener1);
logger.info("testVotingLoop: creating slowMachine2...");
FullJR2VirtualInstanceBuilder slowBuilder2 = newBuilder();
slowBuilder2.setDebugName("slow2").useRepositoryOf(slowMachine1).setConnectorPingTimeout(600).setConnectorPingInterval(999).setMinEventDelay(0);
FullJR2VirtualInstance slowMachine2 = slowBuilder2.fullBuild();
instances.add(slowMachine2);
SimpleTopologyEventListener slowListener2 = new SimpleTopologyEventListener("slow2");
slowMachine2.bindTopologyEventListener(slowListener2);
logger.info("testVotingLoop: creating fastMachine...");
FullJR2VirtualInstanceBuilder fastBuilder = newBuilder();
fastBuilder.setDebugName("fast").useRepositoryOf(slowMachine1).setConnectorPingTimeout(600).setConnectorPingInterval(999).setMinEventDelay(0);
FullJR2VirtualInstance fastMachine = fastBuilder.fullBuild();
instances.add(fastMachine);
SimpleTopologyEventListener fastListener = new SimpleTopologyEventListener("fast");
fastMachine.bindTopologyEventListener(fastListener);
HeartbeatHandler hhSlow1 = slowMachine1.getHeartbeatHandler();
HeartbeatHandler hhSlow2 = slowMachine2.getHeartbeatHandler();
HeartbeatHandler hhFast = fastMachine.getHeartbeatHandler();
Thread.sleep(1000);
logger.info("testVotingLoop: after some initial 1sec sleep no event should yet have been sent");
assertFalse(fastMachine.getDiscoveryService().getTopology().isCurrent());
assertFalse(slowMachine1.getDiscoveryService().getTopology().isCurrent());
assertFalse(slowMachine2.getDiscoveryService().getTopology().isCurrent());
assertNull(fastListener.getLastEvent());
assertNull(slowListener1.getLastEvent());
assertNull(slowListener2.getLastEvent());
// prevent the slow machine from voting
logger.info("testVotingLoop: stopping voting of slowMachine1...");
slowMachine1.stopVoting();
// now let all issue a heartbeat
logger.info("testVotingLoop: letting slow1, slow2 and fast all issue 1 heartbeat");
hhSlow1.issueHeartbeat();
hhSlow2.issueHeartbeat();
hhFast.issueHeartbeat();
// now let the fast one start a new voting, to which
// only the fast one will vote, the slow one doesn't.
// that will cause a voting loop
logger.info("testVotingLoop: let the fast one do a checkView, thus initiate a voting");
hhFast.doCheckView();
Calendar previousVotedAt = null;
for (int i = 0; i < 5; i++) {
logger.info("testVotingLoop: sleeping 1sec...");
Thread.sleep(1000);
logger.info("testVotingLoop: check to see that there is no voting loop...");
// now check the ongoing votings
ResourceResolverFactory factory = fastMachine.getResourceResolverFactory();
ResourceResolver resourceResolver = factory.getServiceResourceResolver(null);
try {
List<VotingView> ongoingVotings = VotingHelper.listOpenNonWinningVotings(resourceResolver, fastMachine.getFullConfig());
assertNotNull(ongoingVotings);
assertEquals(1, ongoingVotings.size());
VotingView ongoingVote = ongoingVotings.get(0);
assertFalse(ongoingVote.isWinning());
assertFalse(ongoingVote.hasVotedYes(slowMachine1.getSlingId()));
assertTrue(ongoingVote.hasVotedYes(slowMachine2.getSlingId()));
final Resource memberResource = ongoingVote.getResource().getChild("members").getChild(slowMachine2.getSlingId());
final ModifiableValueMap memberMap = memberResource.adaptTo(ModifiableValueMap.class);
Property vote = (Property) memberMap.get("vote");
assertEquals(Boolean.TRUE, vote.getBoolean());
Property votedAt = (Property) memberMap.get("votedAt");
if (previousVotedAt == null) {
previousVotedAt = votedAt.getDate();
} else {
assertEquals(previousVotedAt, votedAt.getDate());
}
} catch (Exception e) {
resourceResolver.close();
fail("Exception: " + e);
}
}
}
Aggregations