/* * Test the API: RepImpl.setBackupProhibited would disable the DbBackup in * DbBackup.startBackup, may be caused by Replay.rollback(). */ @Test public void testRollingBackDbBackupAPI() throws Throwable { RepEnvInfo[] repEnvInfo = RepTestUtils.setupEnvInfos(envRoot, 1); ReplicatedEnvironment master = RepTestUtils.joinGroup(repEnvInfo); RepImpl repImpl = RepInternal.getRepImpl(master); DbBackup backupHelper = new DbBackup(master); repImpl.setBackupProhibited(true); try { backupHelper.startBackup(); fail("Should throw out a LogOverwriteException here."); } catch (LogOverwriteException e) { /* Expect a LogOverwriteException here. */ } repImpl.setBackupProhibited(false); try { backupHelper.startBackup(); backupHelper.endBackup(); } catch (Exception e) { fail("Shouldn't get an exception here."); } finally { RepTestUtils.shutdownRepEnvs(repEnvInfo); } }
@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); } }
/* Insert 100 records begins with the beginKey. */ private void doWork(Environment master, String dbName, int beginKey) throws Exception { DatabaseConfig dbConfig = new DatabaseConfig(); dbConfig.setAllowCreate(true); dbConfig.setTransactional(true); /* Insert/Update the records of the database. */ Database db = master.openDatabase(null, dbName, dbConfig); DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); for (int i = 0; i < 100; i++) { IntegerBinding.intToEntry(beginKey + i, key); StringBinding.stringToEntry("herococo", data); db.put(null, key, data); } db.close(); /* * Do a sync at the end of the stage to make sure master and * replica have the same data set. */ VLSN commitVLSN = RepTestUtils.syncGroupToLastCommit(repEnvInfo, repEnvInfo.length); RepTestUtils.checkNodeEquality(commitVLSN, false, repEnvInfo); }
/** * Create a log that will have swathes of cleaned files that follow the replication stream, or are * intermingled in the replication stream. * * @return master */ private Environment setupLogWithCleanedGaps(boolean multipleGaps) throws Exception { db = null; repEnvInfo = RepTestUtils.setupEnvInfos(envRoot, 3, makeEnvConfig()); Environment master = RepTestUtils.joinGroup(repEnvInfo); int masterIdx = findMasterIndex(master); db = openDatabase(master); /* Write some data so there is a replication stream. */ generateData(master, 50, Durability.COMMIT_NO_SYNC, true); /* * Make the master have a low-utilization log, and gate cleaning * with a non-updating global cbvlsn. Shut down the replicas so the * global cbvlsn remains low, and then fill the master with junk. * The junk will either entirely be to the right of the last VLSN, * or (since we can't predict RepGroupDB updates) at least within * the range of the active VLSN range. */ closeReplicas(masterIdx); fillLogWithTraceMsgs(master, 50); if (multipleGaps) { Durability noAck = new Durability(SyncPolicy.NO_SYNC, SyncPolicy.NO_SYNC, ReplicaAckPolicy.NONE); /* Write more data */ generateData(master, 50, noAck, true); /* Make a second cleanup area of junk */ fillLogWithTraceMsgs(master, 50); } CheckpointConfig cc = new CheckpointConfig(); cc.setForce(true); master.checkpoint(cc); EnvironmentStats stats = master.getStats(clearConfig); stats = master.getStats(clearConfig); /* Clean the log */ int totalCleaned = 0; int cleanedThisPass = 0; do { cleanedThisPass = cleanLog(master); totalCleaned += cleanedThisPass; master.checkpoint(cc); stats = master.getStats(clearConfig); logger.info( "after cleaning, cleaner backlog = " + stats.getCleanerBacklog() + " deletionBacklog=" + stats.getFileDeletionBacklog()); } while (cleanedThisPass > 0); assertTrue(totalCleaned > 0); return master; }
/** * Make a thread allocate a vlsn, but then fail before it's tracked by the vlsn index. This * happened in [#20919] when 1.rep environment close was called 2.the repNode was nulled out 3.a * concurrent writing thread got a NPE within its call to LogManager.log because the repNode was * null. This thread exited after it had bumped the vlsn, but before it had entered the vlsn in * the vlsnIndex 4.rep environment close tried to do a checkpoint, but the checkpoint hung. This * fix works by having (3) invalidate the environment, and by having (4) check for an invalidated * environment. */ @Test public void testLoggingFailure() throws DatabaseException, IOException { /* Make a single replicated environment. */ RepEnvInfo[] repEnvInfo = RepTestUtils.setupEnvInfos(envRoot, 1); RepTestUtils.joinGroup(repEnvInfo); /* * Disable cleaning and CBVLSN updating, to control vlsn creation * explicitly. */ Environment env = repEnvInfo[0].getEnv(); EnvironmentMutableConfig config = env.getMutableConfig(); config.setConfigParam("je.env.runCleaner", "false"); env.setMutableConfig(config); LocalCBVLSNUpdater.setSuppressGroupDBUpdates(false); DatabaseConfig dbConfig = new DatabaseConfig(); dbConfig.setTransactional(true); dbConfig.setAllowCreate(true); Database db = env.openDatabase(null, "foo", dbConfig); DatabaseEntry value = new DatabaseEntry(new byte[4]); EnvironmentImpl envImpl = DbInternal.getEnvironmentImpl(env); LogManager logManager = DbInternal.getEnvironmentImpl(env).getLogManager(); /* * Inject an exception into the next call to log() that is made * for a replicated log entry. */ logManager.setDelayVLSNRegisterHook(new ForceException()); VLSNIndex vlsnIndex = ((RepImpl) envImpl).getVLSNIndex(); try { db.put(null, value, value); fail("Should throw exception"); } catch (Exception expected) { assertTrue( "latest=" + vlsnIndex.getLatestAllocatedVal() + " last mapped=" + vlsnIndex.getRange().getLast().getSequence(), vlsnIndex.getLatestAllocatedVal() > vlsnIndex.getRange().getLast().getSequence()); } try { VLSNIndex.AWAIT_CONSISTENCY_MS = 1000; envImpl.awaitVLSNConsistency(); fail("Should throw and break out"); } catch (DatabaseException expected) { } /* Before the fix, this test hung. */ }
/* Start a replication group with 2 nodes and returns the master. */ private ReplicatedEnvironment getMaster() throws Exception { Durability durability = new Durability( Durability.SyncPolicy.WRITE_NO_SYNC, Durability.SyncPolicy.WRITE_NO_SYNC, Durability.ReplicaAckPolicy.ALL); EnvironmentConfig envConfig = RepTestUtils.createEnvConfig(durability); repEnvInfo = RepTestUtils.setupEnvInfos(envRoot, 2, envConfig); return RepTestUtils.joinGroup(repEnvInfo); }
/** * Syncup the group and check for these requirements: - the master has all the data we expect - * the replicas have all the data that is on the master. * * <p>- the last VLSN is not a sync VLSN. We want to ensure that the matchpoint is not the last * VLSN, so the test will need to do rollback * * @throws InterruptedException * @return lastVLSN on the master */ private VLSN checkIfWholeGroupInSync( ReplicatedEnvironment master, RepEnvInfo[] repEnvInfo, RollbackWorkload workload) throws InterruptedException { /* * Make sure we're testing partial rollbacks, and that the replication * stream is poised at a place where the last sync VLSN != lastVLSN. */ VLSN lastVLSN = ensureDistinctLastAndSyncVLSN(master, repEnvInfo); RepTestUtils.syncGroupToVLSN(repEnvInfo, repEnvInfo.length, lastVLSN); /* * All nodes in the group should have the same data, and it should * consist of committed and uncommitted updates. */ assertTrue(workload.containsAllData(master)); /* * TODO: Node equality check is temporarily disabled because it (or * perhaps just the passing of time that allows for a heartbeat) causes * a GroupDB record to be written, which becomes the matchpoint and * defeats the test of partial rollback (because there is none). */ // RepTestUtils.checkNodeEquality(lastVLSN, verbose, repEnvInfo); /* * TODO: The following fails if checkNodeEquality is called. Perhaps * we should just do this here and not above at the top of the method. */ lastVLSN = ensureDistinctLastAndSyncVLSN(master, repEnvInfo); return lastVLSN; }
public void run() { try { /* Get FileLocks. */ FileChannel channel = lockFile.getChannel(); FileLock lockA = channel.lock(1, 1, false); FileLock lockC = channel.lock(3, 1, false); ReplicatedEnvironment master = getMaster(); doWork(master, dbName, 1); /* Release lock A so that read process can do reads. */ lockA.release(); /* Make sure read process get lock B before this process. */ Thread.sleep(sleepTime); /* Get lock B means read process finish reading, do updates. */ FileLock lockB = getLockWithReTry(channel, 2, 1); doWork(master, dbName, 101); /* Release lock B and lock C. */ lockB.release(); lockC.release(); } catch (Exception e) { /* Dump exceptions and exit with value 6. */ e.printStackTrace(); System.exit(7); } finally { RepTestUtils.shutdownRepEnvs(repEnvInfo); closeLockFile(lockFile); } }
@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); }
private void createRepEnvInfo(String sleepTime) throws Throwable { /* * Set a large buffer size and disable the checkpointing, so the * data in the buffer can only be flushed by the LogFlushTask. */ EnvironmentConfig envConfig = RepTestUtils.createEnvConfig(Durability.COMMIT_NO_SYNC); envConfig.setConfigParam(EnvironmentParams.MAX_MEMORY.getName(), "20000000"); envConfig.setConfigParam(EnvironmentParams.LOG_MEM_SIZE.getName(), "120000000"); envConfig.setConfigParam(EnvironmentParams.NUM_LOG_BUFFERS.getName(), "4"); envConfig.setConfigParam(EnvironmentConfig.ENV_RUN_CHECKPOINTER, "false"); /* Configure the log flush task. */ ReplicationConfig repConfig = new ReplicationConfig(); repConfig.setConfigParam(ReplicationConfig.LOG_FLUSH_TASK_INTERVAL, sleepTime); repEnvInfo = RepTestUtils.setupEnvInfos(envRoot, 3, envConfig, repConfig); }
public MultiProcessOpenEnvTest() throws Exception { envRoot = SharedTestUtils.getTestDir(); /* Make rep0 as the environment home. */ File[] envHomes = RepTestUtils.makeRepEnvDirs(envRoot, 2); masterEnvHome = envHomes[0]; replicaEnvHome = envHomes[1]; lockFile = new File(envRoot, LOCK_FILE_NAME); }
@Override @Before public void setUp() throws Exception { super.setUp(); channelFactory = DataChannelFactoryBuilder.construct(RepTestUtils.readRepNetConfig()); protocol = new Protocol(GROUP_NAME, new NameIdPair(NODE_NAME, 1), null, channelFactory); protocol.updateNodeIds(new HashSet<Integer>(Arrays.asList(new Integer(1)))); }
private void openGroup() throws IOException { EnvironmentConfig envConfig = new EnvironmentConfig(); envConfig.setTransactional(true); envConfig.setAllowCreate(true); ReplicationConfig repConfig = new ReplicationConfig(); repConfig.setConfigParam(RepParams.VLSN_LOG_CACHE_SIZE.getName(), "2"); repEnvInfo = RepTestUtils.setupEnvInfos(envRoot, nNodes, envConfig, repConfig); master = RepTestUtils.joinGroup(repEnvInfo); StoreConfig config = new StoreConfig(); config.setAllowCreate(true); config.setTransactional(true); store = new EntityStore(master, "test", config); primaryIndex = store.getPrimaryIndex(Integer.class, AppData.class); }
/** * [#18882] Before this bug fix, this test would result in a java.io.FileNotFoundException out of * FeederReader$SwitchWindow.fillNext. */ @Test public void testDataInWriteQueue() throws Exception { openGroup(); ExecutorService appThreads = Executors.newFixedThreadPool(numThreads); int opsPerThread = numRecords / numThreads; for (int i = 0; i < numThreads; i++) { appThreads.execute(new AppWork(i, opsPerThread)); } appThreads.shutdown(); appThreads.awaitTermination(6000, TimeUnit.SECONDS); VLSN vlsn = RepTestUtils.syncGroupToLastCommit(repEnvInfo, repEnvInfo.length); RepTestUtils.checkNodeEquality(vlsn, verbose, repEnvInfo); closeGroup(); }
@Override @Before public void setUp() throws Exception { super.setUp(); /* Add a secondary node */ repEnvInfo = RepTestUtils.setupExtendEnvInfo(repEnvInfo, 1); repEnvInfo[repEnvInfo.length - 1].getRepConfig().setNodeType(NodeType.SECONDARY); }
private void doReplicaHasGapNetworkRestore(boolean multiGaps) throws Throwable { Durability noAck = new Durability(SyncPolicy.NO_SYNC, SyncPolicy.NO_SYNC, ReplicaAckPolicy.NONE); db = null; try { Environment master = setupLogWithCleanedGaps(multiGaps); int masterIdx = findMasterIndex(master); /* * Write a record, so that we are sure that there will be a * network restore, because we have to cross a checkpoint. */ generateData(master, 1, noAck, false); CheckpointConfig cc = new CheckpointConfig(); master.checkpoint(cc); EnvironmentStats stats = master.getStats(clearConfig); assertEquals(0, stats.getCleanerBacklog()); if (multiGaps) { logger.info("Multigap: deletion backlog = " + stats.getFileDeletionBacklog()); } else { assertEquals(0, stats.getFileDeletionBacklog()); } db.close(); db = null; repEnvInfo[masterIdx].closeEnv(); /* Start up the two replicas */ openReplicas(masterIdx); /* Start the node that had been the master */ try { repEnvInfo[masterIdx].openEnv(); fail("Should be a network restore"); } catch (InsufficientLogException ile) { repEnvInfo[masterIdx].closeEnv(); NetworkRestore restore = new NetworkRestore(); NetworkRestoreConfig config = new NetworkRestoreConfig(); config.setRetainLogFiles(true); restore.execute(ile, config); repEnvInfo[masterIdx].openEnv(); } /* Check its last VLSN and size. */ } catch (Throwable t) { t.printStackTrace(); throw t; } finally { if (db != null) { db.close(); } RepTestUtils.shutdownRepEnvs(repEnvInfo); } }
/* * Test the API: RepImpl.invalidateDbBackups would disable the DbBackup * at endBackup, may be caused by Replay.rollback(). */ @Test public void testRollBackInvalidateDbBackup() throws Exception { RepEnvInfo[] repEnvInfo = RepTestUtils.setupEnvInfos(envRoot, 1); ReplicatedEnvironment master = RepTestUtils.joinGroup(repEnvInfo); final RepImpl repImpl = RepInternal.getRepImpl(master); DbBackup backupHelper = new DbBackup(master); backupHelper.startBackup(); backupHelper.setTestHook( new TestHook<Object>() { public void doHook() { repImpl.invalidateBackups(8L); } public Object getHookValue() { throw new UnsupportedOperationException(); } public void doIOHook() { throw new UnsupportedOperationException(); } public void hookSetup() { throw new UnsupportedOperationException(); } public void doHook(Object obj) { throw new UnsupportedOperationException(); } }); try { backupHelper.endBackup(); fail("Should throw out a LogOverwriteException here."); } catch (LogOverwriteException e) { /* Expect to get a LogOverwriteException here. */ } finally { RepTestUtils.shutdownRepEnvs(repEnvInfo); } }
private void openReplicas(int masterIndex) { RepEnvInfo[] restartList = new RepEnvInfo[2]; int a = 0; for (int i = 0; i < repEnvInfo.length; i++) { if (i != masterIndex) { restartList[a++] = repEnvInfo[i]; } } RepTestUtils.restartGroup(restartList); }
/** * 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); }
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(); } } }
/** Creates a 3 node group and initializes the app classes. */ private void open() throws Exception { /* * ReplicaAckPolicy.ALL is used to ensure that when a master operation * is committed, the change is immediately available on the replica for * testing -- no waiting in the test is needed. */ repEnvInfo = RepTestUtils.setupEnvInfos( envRoot, 3, RepTestUtils.createEnvConfig( new Durability( Durability.SyncPolicy.WRITE_NO_SYNC, Durability.SyncPolicy.WRITE_NO_SYNC, Durability.ReplicaAckPolicy.ALL)), new ReplicationConfig()); masterEnv = RepTestUtils.joinGroup(repEnvInfo); replicaEnv1 = repEnvInfo[1].getEnv(); replicaEnv2 = repEnvInfo[2].getEnv(); /* Load app classes with custom class loader. */ final File evolveParentDir = new File(System.getProperty("testevolvedir")); final ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader(); for (int i = 0; i < N_APP_VERSIONS; i += 1) { final ClassLoader myLoader = new SimpleClassLoader(parentClassLoader, new File(evolveParentDir, "dplUpgrade." + i)); appClasses[i] = Class.forName(APP_IMPL, true /*initialize*/, myLoader); } /* Open v0 app objects. */ masterApp = newAppObject(0); masterApp.open(masterEnv); replicaApp1 = newAppObject(0); replicaApp1.open(replicaEnv1); replicaApp2 = newAppObject(0); replicaApp2.open(replicaEnv2); }
/* * Test the API: RepNode.shutdownNetworkBackup/restartNetworkBackup service * used to disable the service around a replica syncup operation. */ @Test public void testLockout() throws IOException { setExceptionListener(repEnvInfo[0]); repEnvInfo[0].openEnv(); RepNode repNode = repEnvInfo[0].getRepNode(); leaveGroupAllButMaster(); repNode.shutdownNetworkBackup(); File backupDir = new File(repEnvInfo[1].getEnvHome().getCanonicalPath() + ".backup"); backupDir.mkdir(); assertTrue(backupDir.exists()); DataChannelFactory channelFactory = DataChannelFactoryBuilder.construct(RepTestUtils.readRepNetConfig()); EnvironmentImpl envImpl = createEnvImpl(backupDir); try { NetworkBackup backup = new NetworkBackup( repNode.getSocket(), backupDir, new NameIdPair("n1", (short) 1), true, envImpl.getFileManager(), channelFactory); backup.execute(); fail("expected exception service should not have been available"); } catch (ServiceConnectFailedException e) { /* Expected. */ } catch (Exception e) { fail("unexpected exception" + e); } repNode.restartNetworkBackup(); try { NetworkBackup backup = new NetworkBackup( repNode.getSocket(), backupDir, new NameIdPair("n1", (short) 1), true, envImpl.getFileManager(), channelFactory); backup.execute(); } catch (Exception e) { fail("unexpected exception:" + e); } envImpl.abnormalClose(); }
/** Crash the current master, and wait until the group elects a new one. */ private ReplicatedEnvironment crashMasterAndElectNewMaster( ReplicatedEnvironment master, RepEnvInfo[] repEnvInfo) { int masterIndex = RepInternal.getNodeId(master) - 1; logger.info("Crashing " + master.getNodeName()); repEnvInfo[masterIndex].abnormalCloseEnv(); logger.info("Rejoining"); ReplicatedEnvironment newMaster = RepTestUtils.openRepEnvsJoin(repEnvInfo); logger.info("New master = " + newMaster.getNodeName()); return newMaster; }
/** Simulates the scenario where an entire group goes down and is restarted. */ @Test public void testAllJoinLeaveJoinGroup() throws DatabaseException, InterruptedException { createGroup(); ReplicatedEnvironment masterRep = repEnvInfo[0].getEnv(); populateDB(masterRep, TEST_DB_NAME, 100); RepTestUtils.syncGroupToLastCommit(repEnvInfo, repEnvInfo.length); /* Shutdown the entire group. */ closeNodes(repEnvInfo); /* * Restart the group, using a longer join wait time to allow the * secondary to query the primaries a second time after the election is * complete. See RepNode.MASTER_QUERY_INTERVAL. */ final long masterQueryInterval = 10000; restartNodes(JOIN_WAIT_TIME + masterQueryInterval, repEnvInfo); }
@Test public void testNoQuorum() throws DatabaseException, InterruptedException { for (int i = 0; i < 3; i++) { ReplicatedEnvironment rep = repEnvInfo[i].openEnv(); State state = rep.getState(); assertEquals((i == 0) ? State.MASTER : State.REPLICA, state); } RepTestUtils.syncGroupToLastCommit(repEnvInfo, 3); repEnvInfo[1].closeEnv(); repEnvInfo[2].closeEnv(); // A new node joining in the absence of a quorum must fail try { repEnvInfo[3].openEnv(); fail("Expected exception"); } catch (UnknownMasterException e) { /* Expected. */ } }
/** * Verify that a NetworkBackup that's in progress is aborted by repNode.shutdownNetworkRestore() * and therefore during a rollback operation. */ @Test public void testNBAbortOnSyncup() throws IOException, DatabaseException, ServiceConnectFailedException, LoadThresholdExceededException, InsufficientVLSNRangeException { setExceptionListener(repEnvInfo[0]); repEnvInfo[0].openEnv(); final RepNode repNode = repEnvInfo[0].getRepNode(); leaveGroupAllButMaster(); File backupDir = new File(repEnvInfo[1].getEnvHome().getCanonicalPath() + ".backup"); backupDir.mkdir(); DataChannelFactory channelFactory = DataChannelFactoryBuilder.construct(RepTestUtils.readRepNetConfig()); EnvironmentImpl envImpl = createEnvImpl(backupDir); NetworkBackup backup = new NetworkBackup( repNode.getSocket(), backupDir, new NameIdPair("n1", (short) 1), true, envImpl.getFileManager(), channelFactory); CyclicBarrier testBarrier = new CyclicBarrier( 1, new Runnable() { public void run() { /* The syncup should kill the NB */ repNode.shutdownNetworkBackup(); } }); backup.setTestBarrier(testBarrier); try { backup.execute(); fail("Expected exception"); } catch (IOException e) { /* Expected exception as in progress service was terminated. */ } envImpl.abnormalClose(); }
/** * On the master, generate a log that has section A: a lot of records packed together section B: a * lot of junk that gets cleaned away, creating a gap in the log section C: a new section of data * * <p>Bring the replicas down after A is replicated, but before C is written. When the replicas * come up, they will have to be fed by the feeder from point A. */ @Test public void testFeederHasGap() throws Throwable { Durability noAck = new Durability(SyncPolicy.NO_SYNC, SyncPolicy.NO_SYNC, ReplicaAckPolicy.NONE); db = null; try { Environment master = setupLogWithCleanedGaps(false); int masterIdx = findMasterIndex(master); /* * Write a single record, and then junk, so that we are sure there * is a new VLSN, and that the replicas will have to sync up to * this point, across the gap of cleaned junk. */ generateData(master, 1, noAck, false); EnvironmentStats stats = master.getStats(clearConfig); assertEquals(0, stats.getCleanerBacklog()); assertEquals(0, stats.getFileDeletionBacklog()); /* Start up the two replicas */ for (int i = 0; i < repEnvInfo.length; i++) { if (i != masterIdx) { repEnvInfo[i].openEnv(); /* make sure we have up to date data */ readData(repEnvInfo[i].getEnv(), 50); } } } catch (Throwable t) { t.printStackTrace(); throw t; } finally { if (db != null) { db.close(); } RepTestUtils.shutdownRepEnvs(repEnvInfo); } }
private void close(boolean normalShutdown) { try { if (normalShutdown) { replicaApp1.close(); replicaApp2.close(); masterApp.close(); RepTestUtils.shutdownRepEnvs(repEnvInfo); } else { for (RepEnvInfo info : repEnvInfo) { info.abnormalCloseEnv(); } } } finally { repEnvInfo = null; masterEnv = null; replicaEnv1 = null; replicaEnv2 = null; masterApp = null; replicaApp1 = null; replicaApp2 = null; } }
@Test public void testReplicaHasGap() throws Throwable { db = null; try { Environment master = setupLogWithCleanedGaps(false); int masterIdx = findMasterIndex(master); db.close(); db = null; repEnvInfo[masterIdx].closeEnv(); /* Start up the two replicas */ openReplicas(masterIdx); /* Start the master */ try { repEnvInfo[masterIdx].openEnv(); } catch (InsufficientLogException ile) { repEnvInfo[masterIdx].closeEnv(); NetworkRestore restore = new NetworkRestore(); NetworkRestoreConfig config = new NetworkRestoreConfig(); config.setRetainLogFiles(true); restore.execute(ile, config); repEnvInfo[masterIdx].openEnv(); } } catch (Throwable t) { t.printStackTrace(); throw t; } finally { if (db != null) { db.close(); } RepTestUtils.shutdownRepEnvs(repEnvInfo); } }
@Override public void setUp() throws Exception { super.setUp(); RepTestUtils.removeRepEnvironments(envRoot); }