In the previous two sections we looked at the basics of how to create a replicated environment, and what exceptions you can expect to see in a JE HA application. Now we need to combine these two topics in order to examine how you should open a ReplicatedEnvironment handle to an existing replicated environment.
When you open the handle, the underlying HA code will attempt to open a TCP/IP connection to other nodes in the replication group, based on the node's stored replication group metadata or the helper host information that you provide. In doing so, the node will attempt to locate a Master or, failing that, will hold an election in order to select a new Master, if it is an electable node.
Due to issues of timing and network performance, the node may or may not be able to:
locate the master; and
hold an election.
This can happen if there simply are not enough electable nodes available in order for the current node to start up, find the current master, or hold an election. Remember that a majority of the electable nodes registered in the replication group must be available in order to hold an election.
If this situation occurs, the ReplicatedEnvironment constructor will throw an UnknownMasterException. Therefore, typically, it is best that you prepare for this situation by performing the handle creation in a retry loop, as shown in the following code snippet.
In addition, if the Replica has been down for a long enough period of time, it might be so far out of date that it cannot be brought up to date using the normal replication stream. In this case, the ReplicatedEnvironment constructor will throw an InsufficientLogException. See Restoring Log Files for information on how to handle this exception.
private static int REP_HANDLE_RETRY_MAX = 100; ... ReplicatedEnvironment getEnvironment(File envHome, String groupName, String nodeName, String nodeHost, String helperHosts) throws IllegalStateException, InterruptedException { EnvironmentConfig envConfig = new EnvironmentConfig(); envConfig.setAllowCreate(true); envConfig.setTransactional(true); // Identify the node ReplicationConfig repConfig = new ReplicationConfig(); repConfig.setGroupName(groupName); repConfig.setNodeName(nodeName); repConfig.setNodeHostPort(nodeHost); repConfig.setHelperHosts(helperHosts); for (int i = 0; i < REP_HANDLE_RETRY_MAX; i++) { try { return new ReplicatedEnvironment(envHome, repConfig, envConfig); } catch (UnknownMasterException ume) { /* * Insert application specific code here to indicate that * this problem was encountered, such as writing the * condition to a log file. */ Thread.sleep(5 * 1000); continue; } catch (InsufficientLogException ile) { /* A network restore is required, make the necessary calls */ } } throw new IllegalStateException("getEnvironment: reached max retries"); }
Note that for production code, you may want to retry the handle open without any maximum retry limit.