@Override protected void preLogCommitHook() { super.preLogCommitHook(); RepNode rmMasterNode = repEnvInfo[0].getRepNode(); int size = rmMasterNode.getGroup().getAllElectableMembers().size(); int delNodes = ((size & 1) == 1) ? 2 : 1; int closeNodeIndex = (size - delNodes) - 1; /* * The loop below simulates the concurrent removal of a node while * a transaction is in progress. It deletes a sufficient number of * nodes so as to get a lower simple nodes to get to a new lower * simple majority. */ for (int i = repEnvInfo.length - 1; delNodes-- > 0; i--) { repEnvInfo[i].closeEnv(); rmMasterNode.removeMember(repEnvInfo[i].getRepConfig().getNodeName(), delete); } /* * Shut down an additional undeleted Replica to provoke a * lack of acks based on the old simple majority. */ repEnvInfo[closeNodeIndex].closeEnv(); }
private void testMemberRemoveAckInteraction(final boolean delete) { createGroup(groupSize); Transaction txn; Database db; try { MasterTxn.setFactory(new TxnFactory(delete)); ReplicatedEnvironment master = repEnvInfo[0].getEnv(); txn = master.beginTransaction(null, null); /* Write to the environment. */ db = master.openDatabase(txn, "random", dbconfig); db.close(); txn.commit(); } catch (InsufficientAcksException e) { fail("No exception expected."); } finally { MasterTxn.setFactory(null); } }
/** * Test that a timeout in the feeder while attempting to read the group database because other * feeders have it write locked causes the feeder (and replica) to fail, but allows the master to * continue operating. [#23822] */ @Test public void testJoinGroupReadGroupTimeout() throws DatabaseException, InterruptedException { /* Start first node as master */ ReplicatedEnvironment repEnv = repEnvInfo[0].openEnv(); assertEquals("Master node state", State.MASTER, repEnv.getState()); RepImpl repImpl = RepInternal.getRepImpl(repEnv); for (int i = 1; i <= 2; i++) { /* Get a write lock on the RepGroupDB */ final MasterTxn txn = new MasterTxn( repImpl, new TransactionConfig() .setDurability( new Durability( SyncPolicy.SYNC, SyncPolicy.SYNC, ReplicaAckPolicy.SIMPLE_MAJORITY)), repImpl.getNameIdPair()); final DatabaseImpl groupDbImpl = repImpl.getGroupDb(); final DatabaseEntry value = new DatabaseEntry(); final Cursor cursor = DbInternal.makeCursor(groupDbImpl, txn, new CursorConfig()); final OperationStatus status = cursor.getNext(RepGroupDB.groupKeyEntry, value, LockMode.RMW); assertEquals(i + ": Lock group result", OperationStatus.SUCCESS, status); /* Wait longer than the default 500 ms read timeout */ Thread.sleep(600); /* Test both electable and secondary nodes */ if (i == 2) { repEnvInfo[i].getRepConfig().setNodeType(NodeType.SECONDARY); } /* Create a thread that attempts to join another environment */ RepNodeThread repNodeThread = new RepNodeThread(i, i != 1); repNodeThread.start(); /* Wait for attempt to complete */ repNodeThread.join(30000); assertEquals("RN thread alive", false, repNodeThread.isAlive()); if (i == 1) { /* Join attempt should fail for primary */ assertNotNull("Expected RN thread exception", repNodeThread.te); /* Release write lock on RepGroupDB */ cursor.close(); txn.abort(); /* Second join attempt should succeed */ repNodeThread = new RepNodeThread(1); repNodeThread.start(); repNodeThread.join(30000); assertEquals("RN thread alive", false, repNodeThread.isAlive()); assertEquals("RN thread exception", null, repNodeThread.te); } else { /* Join attempt should succeed for secondary */ assertEquals("RN thread exception", null, repNodeThread.te); /* Release write lock on RepGroupDB */ cursor.close(); txn.abort(); } } }