/** * Identifies the master of the replication group, resulting from the last successful election. * This method relies on the helper nodes supplied to the monitor and queries them for the master. * * <p>This method is useful when a Monitor first starts up and the Master needs to be determined. * Once a Monitor is registered and the Listener has been started, it's kept up to date via events * that are delivered to the Listener. * * @return the id associated with the master replication node. * @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 String getMasterNodeName() throws UnknownMasterException { if (shutdown.get()) { throw new IllegalStateException("The monitor has been shutdown"); } return repGroupAdmin.getMasterNodeName(); }
/** * Registers the monitor with the group so that it can be kept informed about the outcome of * elections and group membership changes. The monitor, just like a replication node, is * identified by its nodeName. The Monitor uses the helper nodes to locate a master with which it * can register itself. If the helper nodes are not available the registration will fail. * * <p>A monitor must be registered at least once, if it needs to be kept up to date about ongoing * election results and group changes. Attempts to re-register the same monitor are ignored. * Registration, once it has been completed successfully persists beyond the lifetime of the * Monitor instance and does not need to be repeated. Repeated registrations are benign and merely * confirm that the current monitor configuration is consistent with earlier registrations of this * monitor. * * @return the node that is the current master * @throws EnvironmentFailureException if an unexpected, internal or environment-wide failure * occurs. * @throws IllegalStateException if the monitor has been shutdown, or no helper sockets were * specified at Monitor initialization. */ public ReplicationNode register() throws EnvironmentFailureException { if (shutdown.get()) { throw new IllegalStateException("The monitor has been shutdown"); } if (repGroupAdmin.getHelperSockets().size() == 0) { throw new IllegalStateException("No helper sockets were specified at Monitor initialization"); } RepNodeImpl monitorNode = new RepNodeImpl( nameIdPair, NodeType.MONITOR, monitorConfig.getNodeHostname(), monitorConfig.getNodePort()); /* Ensure that the monitor is part of the group. */ return repGroupAdmin.ensureMonitor(monitorNode); }
/** * 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."); } }