@Test public void testConfigError() { configureForMaxCleaning(5); final RepEnvInfo minfo = repEnvInfo[0]; createGroup(); populateDB(minfo.getEnv(), TEST_DB_NAME, 100); RepEnvInfo nrInfo = repEnvInfo[1]; nrInfo.closeEnv(); shiftVLSNRight(repEnvInfo[0].getEnv()); try { setExceptionListener(nrInfo); nrInfo.openEnv(); fail("exception expected"); } catch (InsufficientLogException e) { NetworkRestore networkRestore = new NetworkRestore(); final ReplicationConfig repConfig = repEnvInfo[0].getRepConfig(); // bad node name repConfig.setNodeName("badname"); ReplicationNode restoreNode = new RepNodeImpl(repConfig); final NetworkRestoreConfig config = new NetworkRestoreConfig(); config.setLogProviders(Arrays.asList(restoreNode)); try { networkRestore.execute(e, config); fail("exception expected"); } catch (IllegalArgumentException iae) { // Expected } } }
@Test public void testLogProviders() throws Exception { configureForMaxCleaning(5); final RepEnvInfo minfo = repEnvInfo[0]; /* Add a secondary node */ repEnvInfo = RepTestUtils.setupExtendEnvInfo(repEnvInfo, 1); final RepEnvInfo sInfo = repEnvInfo[repEnvInfo.length - 1]; sInfo.getRepConfig().setNodeType(NodeType.SECONDARY); createGroup(); populateDB(minfo.getEnv(), TEST_DB_NAME, 100); /* The node that will be use for network restores. */ RepEnvInfo nrInfo = repEnvInfo[1]; /* restore from master. */ doAndCheckRestore(nrInfo, minfo); /* Check restore from specific Replica. */ doAndCheckRestore(nrInfo, repEnvInfo[2]); /* restore from self should fail. */ try { doAndCheckRestore(nrInfo, repEnvInfo[1]); fail("exception expected"); } catch (EnvironmentFailureException e) { // Expected. Cannot restore from just yourself. } /* Restore secondary */ doAndCheckRestore(sInfo, minfo); /* Restore from secondary */ doAndCheckRestore(nrInfo, sInfo); }
@Test public void testDefaultJoinGroupHelper() throws UnknownMasterException, DatabaseException { for (int i = 0; i < repEnvInfo.length; i++) { RepEnvInfo ri = repEnvInfo[i]; if ((i + 1) == repEnvInfo.length) { /* Use a non-master helper for the last replicator. */ ReplicationConfig config = RepTestUtils.createRepConfig((short) (i + 1)); String hpPairs = ""; // Skip the master, use all the other nodes for (int j = 1; j < i; j++) { hpPairs += "," + repEnvInfo[j].getRepConfig().getNodeHostPort(); } hpPairs = hpPairs.substring(1); config.setHelperHosts(hpPairs); File envHome = ri.getEnvHome(); ri = repEnvInfo[i] = new RepEnvInfo( envHome, config, RepTestUtils.createEnvConfig(Durability.COMMIT_SYNC)); } ri.openEnv(); State state = ri.getEnv().getState(); assertEquals((i == 0) ? State.MASTER : State.REPLICA, state); } }
@Test public void testDefaultJoinGroup() throws UnknownMasterException, DatabaseException { createGroup(); ReplicatedEnvironment masterRep = repEnvInfo[0].getEnv(); assertEquals(State.MASTER, masterRep.getState()); leaveGroupAllButMaster(); /* Populates just the master. */ CommitToken ct = populateDB(masterRep, TEST_DB_NAME, 100); /* Replicas should have caught up when they re-open their handles. */ for (RepEnvInfo ri : repEnvInfo) { ReplicatedEnvironment rep = (ri.getEnv() == null) ? ri.openEnv() : ri.getEnv(); VLSN repVLSN = RepInternal.getRepImpl(rep).getVLSNIndex().getRange().getLast(); assertTrue(new VLSN(ct.getVLSN()).compareTo(repVLSN) <= 0); } }
/** * Bounce the master, causing replica1 to switch roles with the master. If a higher appVersion is * specified, the bounced node will also be upgraded. */ private void bounceMaster(final int appVersion) throws Exception { /* Disable updates to RepGroupDB due to LocalCBVLSN updates. */ LocalCBVLSNUpdater.setSuppressGroupDBUpdates(true); for (RepEnvInfo info : repEnvInfo) { if (info.getEnv() == masterEnv) { /* * Sync up the replication group so that node2 doesn't do * hard recovery. */ RepTestUtils.syncGroupToLastCommit(repEnvInfo, repEnvInfo.length); /* Disable replay on replicas. */ shutdownFeeder(info.getRepNode(), replicaEnv1); shutdownFeeder(info.getRepNode(), replicaEnv2); /* Close the master. */ masterApp.close(); masterApp = null; info.closeEnv(); masterEnv = null; /* Force repEnvInfo[2] to the master. */ WaitForMasterListener masterWaiter = new WaitForMasterListener(); replicaEnv2.setStateChangeListener(masterWaiter); RepNode repNode = repEnvInfo[2].getRepNode(); repNode.forceMaster(true); /* Enable the LocalCBVLSN updates. */ LocalCBVLSNUpdater.setSuppressGroupDBUpdates(false); masterWaiter.awaitMastership(); assertTrue(repNode.isMaster()); masterEnv = replicaEnv2; /* Replica2 was elected, swap names with replica1. */ final ReplicatedEnvironment tmpEnv = replicaEnv1; replicaEnv1 = replicaEnv2; replicaEnv2 = tmpEnv; final AppInterface tmpApp = replicaApp1; replicaApp1 = replicaApp2; replicaApp2 = tmpApp; /* Replica1 (or 2, see above) has been elected master. */ masterApp = newAppObject(appVersion); masterApp.adopt(replicaApp1); /* Former master (just upgraded) becomes replica1. */ replicaEnv1 = info.openEnv(); replicaApp1.open(replicaEnv1); break; } } assertNotNull(masterApp); assertSame(masterEnv.getState(), ReplicatedEnvironment.State.MASTER); }
/** * Bounce replica2. No election will take place. If a higher appVersion is specified, the bounced * node will also be upgraded. */ private void bounceReplica2(final int appVersion) throws Exception { replicaApp2.close(); replicaApp2 = null; for (RepEnvInfo info : repEnvInfo) { if (info.getEnv() == replicaEnv2) { info.closeEnv(); replicaEnv2 = info.openEnv(); replicaApp2 = newAppObject(appVersion); replicaApp2.open(replicaEnv2); break; } } assertNotNull(replicaApp2); assertSame(masterEnv.getState(), ReplicatedEnvironment.State.MASTER); }
@Override public void run() { try { ReplicatedEnvironment repenv = replicator.openEnv( new CommitPointConsistencyPolicy( commitToken, RepTestUtils.MINUTE_MS, TimeUnit.MILLISECONDS)); assertEquals(ReplicatedEnvironment.State.REPLICA, repenv.getState()); ReplicatedEnvironmentStats stats = replicator.getEnv().getRepStats(StatsConfig.DEFAULT); assertEquals(1, stats.getTrackerVLSNConsistencyWaits()); assertTrue(stats.getTrackerVLSNConsistencyWaitMs() > 0); } catch (UnknownMasterException e) { testException = e; throw new RuntimeException(e); } catch (DatabaseException e) { testException = e; throw new RuntimeException(e); } }
public void openEnv() { try { Durability durability = new Durability( Durability.SyncPolicy.WRITE_NO_SYNC, Durability.SyncPolicy.WRITE_NO_SYNC, Durability.ReplicaAckPolicy.ALL); EnvironmentConfig envConfig = RepTestUtils.createEnvConfig(durability); ReplicationConfig repConfig = RepTestUtils.createRepConfig(1); repEnvInfo = RepTestUtils.setupEnvInfo(envHome, envConfig, repConfig, null); repEnvInfo.openEnv(); Thread.sleep(sleepTime); } catch (EnvironmentLockedException e) { /* * Exit the process with value 1, don't print out the exception * since it's expected. */ System.exit(1); } catch (UnsupportedOperationException e) { /* * Exit the process with value 2, don't print out the exception * since it's expected. * * Note: this exception thrown because we can't start a * replicated Environment on an existed standalone Environment. */ System.exit(2); } catch (Exception e) { /* Dump unexpected exceptions, exit processs with value 3. */ e.printStackTrace(); System.exit(3); } finally { if (repEnvInfo.getEnv() != null) { repEnvInfo.closeEnv(); } } }
private void flushLogAndCrash(RepEnvInfo replica) { DbInternal.getEnvironmentImpl(replica.getEnv()).getLogManager().flush(); replica.abnormalCloseEnv(); }
/** * Since the master never dies in this test, no rollbacks should occur, but no data should be lost * either. * * <p>TODO: Should the workload param be of a different class (not a RollbackWorkload), since its * masterSteadyWork method is only called here? */ private void replicasDieAndRejoin(RollbackWorkload workload, int numIterations) throws Throwable { RepEnvInfo[] repEnvInfo = null; try { /* Create a 3 node group. Assign identities. */ repEnvInfo = RepTestUtils.setupEnvInfos(envRoot, 3); ReplicatedEnvironment master = RepTestUtils.joinGroup(repEnvInfo); logger.severe("master=" + master); RepEnvInfo replicaA = null; RepEnvInfo replicaB = null; for (RepEnvInfo info : repEnvInfo) { if (info.getEnv().getState().isMaster()) { continue; } if (replicaA == null) { replicaA = info; } else { replicaB = info; } } /* * For the sake of easy test writing, make sure numIterations is an * even number. */ assertTrue((numIterations % 2) == 0); replicaA.abnormalCloseEnv(); for (int i = 0; i < numIterations; i++) { workload.masterSteadyWork(master); waitForReplicaToSync(master, repEnvInfo); if ((i % 2) == 0) { flushLogAndCrash(replicaB); replicaA.openEnv(); } else { flushLogAndCrash(replicaA); replicaB.openEnv(); } waitForReplicaToSync(master, repEnvInfo); } replicaA.openEnv(); VLSN lastVLSN = RepInternal.getRepImpl(master).getVLSNIndex().getRange().getLast(); RepTestUtils.syncGroupToVLSN(repEnvInfo, repEnvInfo.length, lastVLSN); assertTrue(workload.containsAllData(master)); RepTestUtils.checkNodeEquality(lastVLSN, verbose, repEnvInfo); workload.close(); for (RepEnvInfo repi : repEnvInfo) { /* * We're done with the test. Bringing down these replicators * forcibly, without closing transactions and whatnot. */ repi.abnormalCloseEnv(); } } catch (Throwable e) { e.printStackTrace(); throw e; } }