private void promote()

in src/main/java/org/apache/sling/discovery/impl/cluster/voting/VotingHandler.java [374:520]


    private void promote(final ResourceResolver resourceResolver,
            final Resource winningVoteResource) throws PersistenceException {
        Resource previousViewsResource = ResourceHelper
                .getOrCreateResource(
                        resourceResolver,
                        config.getPreviousViewPath());
        final Resource establishedViewsResource = ResourceHelper
                .getOrCreateResource(
                        resourceResolver,
                        config.getEstablishedViewPath());
        final Resource ongoingVotingsResource = ResourceHelper
                .getOrCreateResource(
                        resourceResolver,
                        config.getOngoingVotingsPath());

    	if (logger.isDebugEnabled()) {
	        logger.debug("promote: previousViewsResource="
	                + previousViewsResource.getPath());
	        logger.debug("promote: establishedViewsResource="
	                + establishedViewsResource.getPath());
	        logger.debug("promote: ongoingVotingsResource="
	                + ongoingVotingsResource.getPath());
	        logger.debug("promote: winningVoteResource="
	                + winningVoteResource.getPath());
    	}

        // step 1: remove any nodes under previousViews
        final Iterator<Resource> it1 = previousViewsResource.getChildren().iterator();
        try{
            while (it1.hasNext()) {
                Resource previousView = it1.next();
                resourceResolver.delete(previousView);
            }
        } catch(PersistenceException e) {
            // if we cannot delete, apply workaround suggested in SLING-3785
            logger.error("promote: Could not delete a previous view - trying move next: "+e, e);
            ResourceHelper.moveResource(previousViewsResource, config.getPreviousViewPath()+"_trash_"+UUID.randomUUID().toString());
            logger.info("promote: recreating the previousviews node");
            previousViewsResource = ResourceHelper
                    .getOrCreateResource(
                            resourceResolver,
                            config.getPreviousViewPath());
        }

        // step 2: retire the existing established view.
        // Note that there must always only be one. But if there's more, retire
        // them all now.
        final Iterator<Resource> it = establishedViewsResource.getChildren()
                .iterator();
        boolean first = true;
        while (it.hasNext()) {
            Resource retiredView = it.next();
            if (first) {
                first = !first;
            	if (logger.isDebugEnabled()) {
	                logger.debug("promote: moving the old established view to previous views: "
	                        + retiredView.getPath());
            	}
                ResourceHelper.moveResource(retiredView,
                        previousViewsResource.getPath()
                                + "/" + retiredView.getName());
            } else {
            	if (logger.isDebugEnabled()) {
	                logger.debug("promote: retiring an erroneously additionally established node "
	                        + retiredView.getPath());
            	}
                resourceResolver.delete(retiredView);
            }
        }

        // step 3: move the winning vote resource under the
        // establishedViewsResource

        // 3a: set the leaderid
        final Iterator<Resource> it2 = winningVoteResource.getChild("members")
                .getChildren().iterator();
        String leaderElectionId = null;
        String leaderid = null;
        int membersCount = 0;
        while (it2.hasNext()) {
            Resource aMember = it2.next();
            membersCount++;
            String leid = aMember.adaptTo(ValueMap.class).get(
                    "leaderElectionId", String.class);
            if (leaderElectionId == null
                    || (leid != null && leid.compareTo(leaderElectionId) < 0)) {
                leaderElectionId = leid;
                leaderid = aMember.getName();
            }
        }
    	if (logger.isDebugEnabled()) {
	        logger.debug("promote: leader is " + leaderid
	                + " - with leaderElectionId=" + leaderElectionId);
    	}
        ModifiableValueMap winningVoteMap = winningVoteResource.adaptTo(ModifiableValueMap.class);
        winningVoteMap.put("leaderId", leaderid);
        winningVoteMap.put("leaderElectionId", leaderElectionId);
        winningVoteMap.put("promotedAt", Calendar.getInstance());
        winningVoteMap.put("promotedBy", slingId);

        // 3b: move the result under /established
        final String newEstablishedViewPath = establishedViewsResource.getPath()
                + "/" + winningVoteResource.getName();
        logger.info("promote: promoting to new established node (#members: " + membersCount + ", path: "
                + newEstablishedViewPath + ")");
        ResourceHelper.moveResource(winningVoteResource, newEstablishedViewPath);

        // step 4: delete all ongoing votings...
        final Iterable<Resource> ongoingVotingsChildren = ongoingVotingsResource
                .getChildren();
        if (ongoingVotingsChildren != null) {
            Iterator<Resource> it4 = ongoingVotingsChildren.iterator();
            while (it4.hasNext()) {
                Resource anOngoingVoting = it4.next();
                logger.info("promote: deleting ongoing voting: "+anOngoingVoting.getName());
                resourceResolver.delete(anOngoingVoting);
            }
        }

        // step 5: make sure there are no duplicate ongoingVotings nodes
        // created. if so, cleanup
        final Iterator<Resource> it5 = ongoingVotingsResource.getParent()
                .getChildren().iterator();
        while (it5.hasNext()) {
            Resource resource = it5.next();
            if (!resource
                    .getPath()
                    .startsWith(
                            config.getOngoingVotingsPath())) {
                continue;
            }
            if (resource
                    .getPath()
                    .equals(config.getOngoingVotingsPath())) {
                // then it's [0] so to speak .. which we're not cleaning up
                continue;
            }
            logger.warn("promote: cleaning up a duplicate ongoingVotingPath: "
                    + resource.getPath());
            resourceResolver.delete(resource);
        }

        logger.debug("promote: done with promotiong. saving.");
        resourceResolver.commit();
        logger.info("promote: promotion done (#members: " + membersCount + ", path: "
                + newEstablishedViewPath + ")");
    }