use of com.alipay.sofa.jraft.closure.SynchronizedClosure in project sofa-jraft by sofastack.
the class NodeTest method testChangePeersStepsDownInJointConsensus.
@Test
public void testChangePeersStepsDownInJointConsensus() throws Exception {
final List<PeerId> peers = new ArrayList<>();
final PeerId peer0 = JRaftUtils.getPeerId("127.0.0.1:5006");
final PeerId peer1 = JRaftUtils.getPeerId("127.0.0.1:5007");
final PeerId peer2 = JRaftUtils.getPeerId("127.0.0.1:5008");
final PeerId peer3 = JRaftUtils.getPeerId("127.0.0.1:5009");
// start single cluster
peers.add(peer0);
final TestCluster cluster = new TestCluster("testChangePeersStepsDownInJointConsensus", this.dataPath, peers);
assertTrue(cluster.start(peer0.getEndpoint()));
cluster.waitLeader();
Node leader = cluster.getLeader();
assertNotNull(leader);
this.sendTestTaskAndWait(leader);
// start peer1-3
assertTrue(cluster.start(peer1.getEndpoint()));
assertTrue(cluster.start(peer2.getEndpoint()));
assertTrue(cluster.start(peer3.getEndpoint()));
final Configuration conf = new Configuration();
conf.addPeer(peer0);
conf.addPeer(peer1);
conf.addPeer(peer2);
conf.addPeer(peer3);
// change peers
final SynchronizedClosure done = new SynchronizedClosure();
leader.changePeers(conf, done);
assertTrue(done.await().isOk());
// stop peer3
assertTrue(cluster.stop(peer3.getEndpoint()));
conf.removePeer(peer0);
conf.removePeer(peer1);
// Change peers to [peer2, peer3], which must fail since peer3 is stopped
done.reset();
leader.changePeers(conf, done);
Assert.assertEquals(RaftError.EPERM, done.await().getRaftError());
LOG.info(done.getStatus().toString());
assertFalse(((NodeImpl) leader).getConf().isStable());
leader = cluster.getLeader();
assertNull(leader);
assertTrue(cluster.start(peer3.getEndpoint()));
Thread.sleep(1000);
cluster.waitLeader();
leader = cluster.getLeader();
final List<PeerId> thePeers = leader.listPeers();
assertTrue(thePeers.size() > 0);
assertEquals(conf.getPeerSet(), new HashSet<>(thePeers));
cluster.stopAll();
}
use of com.alipay.sofa.jraft.closure.SynchronizedClosure in project sofa-jraft by sofastack.
the class NodeTest method startChangePeersThread.
private Future<?> startChangePeersThread(final ChangeArg arg) {
final Set<RaftError> expectedErrors = new HashSet<>();
expectedErrors.add(RaftError.EBUSY);
expectedErrors.add(RaftError.EPERM);
expectedErrors.add(RaftError.ECATCHUP);
return Utils.runInThread(() -> {
try {
while (!arg.stop) {
arg.c.waitLeader();
final Node leader = arg.c.getLeader();
if (leader == null) {
continue;
}
// select peers in random
final Configuration conf = new Configuration();
if (arg.dontRemoveFirstPeer) {
conf.addPeer(arg.peers.get(0));
}
for (int i = 0; i < arg.peers.size(); i++) {
final boolean select = ThreadLocalRandom.current().nextInt(64) < 32;
if (select && !conf.contains(arg.peers.get(i))) {
conf.addPeer(arg.peers.get(i));
}
}
if (conf.isEmpty()) {
LOG.warn("No peer has been selected");
continue;
}
final SynchronizedClosure done = new SynchronizedClosure();
leader.changePeers(conf, done);
done.await();
assertTrue(done.getStatus().toString(), done.getStatus().isOk() || expectedErrors.contains(done.getStatus().getRaftError()));
}
} catch (final InterruptedException e) {
LOG.error("ChangePeersThread is interrupted", e);
}
});
}
use of com.alipay.sofa.jraft.closure.SynchronizedClosure in project sofa-jraft by sofastack.
the class NodeTest method testTripleNodesWithLearners.
@Test
public void testTripleNodesWithLearners() throws Exception {
final List<PeerId> peers = TestUtils.generatePeers(3);
final TestCluster cluster = new TestCluster("unittest", this.dataPath, peers);
for (final PeerId peer : peers) {
assertTrue(cluster.start(peer.getEndpoint()));
}
// elect leader
cluster.waitLeader();
// get leader
final Node leader = cluster.getLeader();
assertNotNull(leader);
assertEquals(3, leader.listPeers().size());
assertTrue(leader.listLearners().isEmpty());
assertTrue(leader.listAliveLearners().isEmpty());
{
// Adds a learner
SynchronizedClosure done = new SynchronizedClosure();
PeerId learnerPeer = new PeerId(TestUtils.getMyIp(), TestUtils.INIT_PORT + 3);
// Start learner
assertTrue(cluster.startLearner(learnerPeer));
leader.addLearners(Arrays.asList(learnerPeer), done);
assertTrue(done.await().isOk());
assertEquals(1, leader.listAliveLearners().size());
assertEquals(1, leader.listLearners().size());
}
// apply tasks to leader
this.sendTestTaskAndWait(leader);
{
final ByteBuffer data = ByteBuffer.wrap("no closure".getBytes());
final Task task = new Task(data, null);
leader.apply(task);
}
{
// task with TaskClosure
final ByteBuffer data = ByteBuffer.wrap("task closure".getBytes());
final Vector<String> cbs = new Vector<>();
final CountDownLatch latch = new CountDownLatch(1);
final Task task = new Task(data, new TaskClosure() {
@Override
public void run(final Status status) {
cbs.add("apply");
latch.countDown();
}
@Override
public void onCommitted() {
cbs.add("commit");
}
});
leader.apply(task);
latch.await();
assertEquals(2, cbs.size());
assertEquals("commit", cbs.get(0));
assertEquals("apply", cbs.get(1));
}
assertEquals(4, cluster.getFsms().size());
assertEquals(2, cluster.getFollowers().size());
assertEquals(1, cluster.getLearners().size());
cluster.ensureSame(-1);
{
// Adds another learner
SynchronizedClosure done = new SynchronizedClosure();
PeerId learnerPeer = new PeerId(TestUtils.getMyIp(), TestUtils.INIT_PORT + 4);
// Start learner
assertTrue(cluster.startLearner(learnerPeer));
leader.addLearners(Arrays.asList(learnerPeer), done);
assertTrue(done.await().isOk());
assertEquals(2, leader.listAliveLearners().size());
assertEquals(2, leader.listLearners().size());
}
{
// stop two followers
for (Node follower : cluster.getFollowers()) {
assertTrue(cluster.stop(follower.getNodeId().getPeerId().getEndpoint()));
}
// send a new task
final ByteBuffer data = ByteBuffer.wrap("task closure".getBytes());
SynchronizedClosure done = new SynchronizedClosure();
leader.apply(new Task(data, done));
// should fail
assertFalse(done.await().isOk());
assertEquals(RaftError.EPERM, done.getStatus().getRaftError());
// One peer with two learners.
assertEquals(3, cluster.getFsms().size());
cluster.ensureSame(-1);
}
cluster.stopAll();
}
use of com.alipay.sofa.jraft.closure.SynchronizedClosure in project sofa-jraft by sofastack.
the class NodeTest method testChangePeers.
@Test
public void testChangePeers() throws Exception {
final PeerId peer0 = new PeerId(TestUtils.getMyIp(), TestUtils.INIT_PORT);
final TestCluster cluster = new TestCluster("testChangePeers", this.dataPath, Collections.singletonList(peer0));
assertTrue(cluster.start(peer0.getEndpoint()));
cluster.waitLeader();
Node leader = cluster.getLeader();
this.sendTestTaskAndWait(leader);
for (int i = 1; i < 10; i++) {
final PeerId peer = new PeerId(TestUtils.getMyIp(), TestUtils.INIT_PORT + i);
assertTrue(cluster.start(peer.getEndpoint(), true, 300));
}
for (int i = 0; i < 9; i++) {
cluster.waitLeader();
leader = cluster.getLeader();
assertNotNull(leader);
PeerId peer = new PeerId(TestUtils.getMyIp(), peer0.getEndpoint().getPort() + i);
Assert.assertEquals(peer, leader.getNodeId().getPeerId());
peer = new PeerId(TestUtils.getMyIp(), peer0.getEndpoint().getPort() + i + 1);
final SynchronizedClosure done = new SynchronizedClosure();
leader.changePeers(new Configuration(Collections.singletonList(peer)), done);
assertTrue(done.await().isOk());
}
assertTrue(cluster.ensureSame());
cluster.stopAll();
}
use of com.alipay.sofa.jraft.closure.SynchronizedClosure in project sofa-jraft by sofastack.
the class NodeTest method testResetLearners.
@Test
public void testResetLearners() throws Exception {
final List<PeerId> peers = TestUtils.generatePeers(3);
final LinkedHashSet<PeerId> learners = new LinkedHashSet<>();
for (int i = 0; i < 3; i++) {
learners.add(new PeerId(TestUtils.getMyIp(), TestUtils.INIT_PORT + 3 + i));
}
final TestCluster cluster = new TestCluster("unittest", this.dataPath, peers, learners, 300);
for (final PeerId peer : peers) {
assertTrue(cluster.start(peer.getEndpoint()));
}
for (final PeerId peer : learners) {
assertTrue(cluster.startLearner(peer));
}
// elect leader
cluster.waitLeader();
Node leader = cluster.getLeader();
assertEquals(3, leader.listAlivePeers().size());
assertEquals(3, leader.listAliveLearners().size());
this.sendTestTaskAndWait(leader);
Thread.sleep(500);
List<MockStateMachine> fsms = cluster.getFsms();
assertEquals(6, fsms.size());
cluster.ensureSame();
{
// Reset learners to 2 nodes
PeerId learnerPeer = new PeerId(TestUtils.getMyIp(), TestUtils.INIT_PORT + 3);
learners.remove(learnerPeer);
assertEquals(2, learners.size());
SynchronizedClosure done = new SynchronizedClosure();
leader.resetLearners(new ArrayList<>(learners), done);
assertTrue(done.await().isOk());
assertEquals(2, leader.listAliveLearners().size());
assertEquals(2, leader.listLearners().size());
this.sendTestTaskAndWait(leader);
Thread.sleep(500);
assertEquals(6, fsms.size());
// get the removed learner's fsm
MockStateMachine fsm = fsms.remove(3);
assertEquals(fsm.getAddress(), learnerPeer.getEndpoint());
// Ensure no more logs replicated to the removed learner.
assertTrue(cluster.getLeaderFsm().getLogs().size() > fsm.getLogs().size());
assertEquals(cluster.getLeaderFsm().getLogs().size(), 2 * fsm.getLogs().size());
}
{
// remove another learner
PeerId learnerPeer = new PeerId(TestUtils.getMyIp(), TestUtils.INIT_PORT + 4);
SynchronizedClosure done = new SynchronizedClosure();
leader.removeLearners(Arrays.asList(learnerPeer), done);
assertTrue(done.await().isOk());
this.sendTestTaskAndWait(leader);
Thread.sleep(500);
// get the removed learner's fsm
MockStateMachine fsm = fsms.remove(3);
assertEquals(fsm.getAddress(), learnerPeer.getEndpoint());
// Ensure no more logs replicated to the removed learner.
assertTrue(cluster.getLeaderFsm().getLogs().size() > fsm.getLogs().size());
assertEquals(cluster.getLeaderFsm().getLogs().size(), fsm.getLogs().size() / 2 * 3);
}
assertEquals(3, leader.listAlivePeers().size());
assertEquals(1, leader.listAliveLearners().size());
assertEquals(1, leader.listLearners().size());
cluster.stopAll();
}
Aggregations