@Override public void providersChanged(Set<Node> nodes) { if (this.elected(nodes)) { if (!this.master.get()) { ClusteringServerLogger.ROOT_LOGGER.electedMaster( this.singletonServiceName.getCanonicalName()); this.singletonDispatcher.stopOldMaster(); this.startNewMaster(); } } else if (this.master.get()) { ClusteringServerLogger.ROOT_LOGGER.electedSlave(this.singletonServiceName.getCanonicalName()); this.stopOldMaster(); } }
private boolean elected(Set<Node> candidates) { int size = candidates.size(); if (size < this.quorum) { ClusteringServerLogger.ROOT_LOGGER.quorumNotReached( this.singletonServiceName.getCanonicalName(), this.quorum); return false; } else if (size == this.quorum) { ClusteringServerLogger.ROOT_LOGGER.quorumJustReached( this.singletonServiceName.getCanonicalName(), this.quorum); } Node elected = this.election(candidates); if (elected != null) { ClusteringServerLogger.ROOT_LOGGER.elected( elected.getName(), this.singletonServiceName.getCanonicalName()); } return (elected != null) ? elected.equals(this.group.getValue().getLocalNode()) : false; }
@Override public AtomicReference<T> getValueRef() { try { Map<Node, CommandResponse<AtomicReference<T>>> results = Collections.emptyMap(); while (results.isEmpty()) { if (!SingletonService.this.started) { throw new IllegalStateException( ClusteringServerLogger.ROOT_LOGGER.notStarted( SingletonService.this.singletonServiceName.getCanonicalName())); } results = SingletonService.this.dispatcher.executeOnCluster(new SingletonValueCommand<T>()); Iterator<CommandResponse<AtomicReference<T>>> responses = results.values().iterator(); while (responses.hasNext()) { if (responses.next().get() == null) { // Prune non-master results responses.remove(); } } // We expect only 1 result int count = results.size(); if (count > 1) { // This would mean there are multiple masters! throw ClusteringServerLogger.ROOT_LOGGER.unexpectedResponseCount( SingletonService.this.singletonServiceName.getCanonicalName(), count); } if (count == 0) { ClusteringServerLogger.ROOT_LOGGER.noResponseFromMaster( SingletonService.this.singletonServiceName.getCanonicalName()); // Verify whether there is no master because a quorum was not reached during the last // election if (SingletonService.this.registration.getProviders().size() < SingletonService.this.quorum) { return new AtomicReference<>(); } // Otherwise, we're in the midst of a new master election, so just try again Thread.yield(); } } return results.values().iterator().next().get(); } catch (Exception e) { throw new IllegalStateException(e); } }
private void startNewMaster() { this.master.set(true); ServiceController<?> service = this.container.getRequiredService(this.targetServiceName); try { ServiceContainerHelper.start(service); } catch (StartException e) { ClusteringServerLogger.ROOT_LOGGER.serviceStartFailed( e, this.targetServiceName.getCanonicalName()); ServiceContainerHelper.stop(service); } }