/** * Returns the current composition of the group. It does so by first querying the helpers to * determine the master and then obtaining the group information from the master. * * @return an instance of RepGroup denoting the current composition of the group * @throws UnknownMasterException if the master could not be determined from the set of helpers * made available to the Monitor. * @throws EnvironmentFailureException if an unexpected, internal or environment-wide failure * occurs. * @throws IllegalStateException if the monitor has been shutdown. */ public ReplicationGroup getGroup() throws UnknownMasterException, DatabaseException { if (shutdown.get()) { throw new IllegalStateException("The monitor has been shutdown"); } /* * TODO: Should we use this information to update the helper set as an * optimization? */ return repGroupAdmin.getGroup(); }
/** * Starts the Listener so it's actively listening for election results and broadcasts of * replication group changes. * * <p>The Monitor must have been previously registered with the replication group via the <code> * register()</code> method so that other nodes in the group are aware of it and can keep it * current. If the monitor has not been registered, it will not be updated, that is, its listener * will not be invoked. The registration needs to be done exactly once. * * <p>Once the registration has been completed, the Monitor can start listening even when none of * the other nodes in the group are available. It will be contacted automatically by the other * nodes when they come up and hold a successful election. * * <p>Invoking <code>startListener</code> results in a synchronous callback to the application via * the {@link MonitorChangeListener#notify(NewMasterEvent)} method, if there is a current Master. * If there is no Master at this time then the callback takes place asynchronously, after the * method returns, when a Master is eventually elected. * * @param newListener the listener used to monitor events of interest. * @throws EnvironmentFailureException if an unexpected, internal or environment-wide failure * occurs. * @throws IOException if the monitor socket could not be set up * @throws IllegalArgumentException if an invalid parameter is specified. * @throws IllegalStateException if the monitor has been shutdown, or a listener has already been * established. */ public void startListener(MonitorChangeListener newListener) throws DatabaseException, IOException { if (shutdown.get()) { throw new IllegalStateException("The monitor has been shutdown"); } if (newListener == null) { throw new IllegalArgumentException( "A MonitorChangeListener must be associated with " + " this Monitor when invoking this method"); } if (this.monitorChangeListener != null) { throw new IllegalStateException("A Listener has already been established"); } this.monitorChangeListener = newListener; serviceDispatcher = new ServiceDispatcher(monitorConfig.getNodeSocketAddress()); serviceDispatcher.start(); Protocol electionProtocol = new Protocol( TimebasedProposalGenerator.getParser(), MasterValue.getParser(), monitorConfig.getGroupName(), nameIdPair, null); learner = new Learner(electionProtocol, serviceDispatcher, nameIdPair); serviceDispatcher.register(new MonitorService(this, serviceDispatcher)); masterChangeListener = new MasterChangeListener(); learner.addListener(masterChangeListener); learner.start(); try { /* Notify the listener about the current master. */ final ReplicationGroup repGroup = repGroupAdmin.getGroup(); final RepGroupImpl group = RepInternal.getRepGroupImpl(repGroup); /* * In the absence of a network failure, the query should result in * a call to the notify method of MonitorChanegListener. */ learner.queryForMaster(group.getLearnerSockets()); /* Notify JoinGroupEvents for those current active nodes. */ notifyJoinGroupEventsForActiveNodes(repGroup); } catch (UnknownMasterException ume) { /* The Listener will be informed when a Master is elected. */ LoggerUtils.logMsg(logger, formatter, Level.INFO, "No current master."); } }