Search in sources :

Example 1 with VotingView

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);
}
Also used : Resource(org.apache.sling.api.resource.Resource) VotingView(org.apache.sling.discovery.impl.cluster.voting.VotingView) VotingView(org.apache.sling.discovery.impl.cluster.voting.VotingView) View(org.apache.sling.discovery.impl.common.View) PersistenceException(org.apache.sling.api.resource.PersistenceException) BundleException(org.osgi.framework.BundleException) LoginException(org.apache.sling.api.resource.LoginException)

Example 2 with VotingView

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);
        }
    }
}
Also used : FullJR2VirtualInstance(org.apache.sling.discovery.impl.setup.FullJR2VirtualInstance) Calendar(java.util.Calendar) Resource(org.apache.sling.api.resource.Resource) ModifiableValueMap(org.apache.sling.api.resource.ModifiableValueMap) FullJR2VirtualInstanceBuilder(org.apache.sling.discovery.impl.setup.FullJR2VirtualInstanceBuilder) ResourceResolverFactory(org.apache.sling.api.resource.ResourceResolverFactory) ResourceResolver(org.apache.sling.api.resource.ResourceResolver) VotingView(org.apache.sling.discovery.impl.cluster.voting.VotingView) Property(javax.jcr.Property) Test(org.junit.Test)

Aggregations

Resource (org.apache.sling.api.resource.Resource)2 VotingView (org.apache.sling.discovery.impl.cluster.voting.VotingView)2 Calendar (java.util.Calendar)1 Property (javax.jcr.Property)1 LoginException (org.apache.sling.api.resource.LoginException)1 ModifiableValueMap (org.apache.sling.api.resource.ModifiableValueMap)1 PersistenceException (org.apache.sling.api.resource.PersistenceException)1 ResourceResolver (org.apache.sling.api.resource.ResourceResolver)1 ResourceResolverFactory (org.apache.sling.api.resource.ResourceResolverFactory)1 View (org.apache.sling.discovery.impl.common.View)1 FullJR2VirtualInstance (org.apache.sling.discovery.impl.setup.FullJR2VirtualInstance)1 FullJR2VirtualInstanceBuilder (org.apache.sling.discovery.impl.setup.FullJR2VirtualInstanceBuilder)1 Test (org.junit.Test)1 BundleException (org.osgi.framework.BundleException)1