use of org.apache.zookeeper.server.quorum.Leader.Proposal in project zookeeper by apache.
the class QuorumPeerMainTest method testFailedTxnAsPartOfQuorumLoss.
@Test
public void testFailedTxnAsPartOfQuorumLoss() throws Exception {
final int LEADER_TIMEOUT_MS = 10_000;
// 1. start up server and wait for leader election to finish
ClientBase.setupTestEnv();
final int SERVER_COUNT = 3;
servers = LaunchServers(SERVER_COUNT);
waitForAll(servers, States.CONNECTED);
// we need to shutdown and start back up to make sure that the create session isn't the first transaction since
// that is rather innocuous.
servers.shutDownAllServers();
waitForAll(servers, States.CONNECTING);
servers.restartAllServersAndClients(this);
waitForAll(servers, States.CONNECTED);
// 2. kill all followers
int leader = servers.findLeader();
Map<Long, Proposal> outstanding = servers.mt[leader].main.quorumPeer.leader.outstandingProposals;
// increase the tick time to delay the leader going to looking
int previousTick = servers.mt[leader].main.quorumPeer.tickTime;
servers.mt[leader].main.quorumPeer.tickTime = LEADER_TIMEOUT_MS;
// let the previous tick on the leader exhaust itself so the new tick time takes effect
Thread.sleep(previousTick);
LOG.warn("LEADER {}", leader);
for (int i = 0; i < SERVER_COUNT; i++) {
if (i != leader) {
servers.mt[i].shutdown();
}
}
// 3. start up the followers to form a new quorum
for (int i = 0; i < SERVER_COUNT; i++) {
if (i != leader) {
servers.mt[i].start();
}
}
// 4. wait one of the follower to be the new leader
for (int i = 0; i < SERVER_COUNT; i++) {
if (i != leader) {
// Recreate a client session since the previous session was not persisted.
servers.restartClient(i, this);
waitForOne(servers.zk[i], States.CONNECTED);
}
}
// which means it acked from itself
try {
servers.zk[leader].create("/zk" + leader, "zk".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
fail("create /zk" + leader + " should have failed");
} catch (KeeperException e) {
}
// just make sure that we actually did get it in process at the
// leader
// there can be extra sessionClose proposals
assertTrue(outstanding.size() > 0);
Proposal p = findProposalOfType(outstanding, OpCode.create);
LOG.info("Old leader id: {}. All proposals: {}", leader, outstanding);
assertNotNull(p, "Old leader doesn't have 'create' proposal");
// make sure it has a chance to write it to disk
int sleepTime = 0;
Long longLeader = (long) leader;
while (!p.qvAcksetPairs.get(0).getAckset().contains(longLeader)) {
if (sleepTime > 2000) {
fail("Transaction not synced to disk within 1 second " + p.qvAcksetPairs.get(0).getAckset() + " expected " + leader);
}
Thread.sleep(100);
sleepTime += 100;
}
// 6. wait for the leader to quit due to not enough followers and come back up as a part of the new quorum
LOG.info("Waiting for leader {} to timeout followers", leader);
sleepTime = 0;
Follower f = servers.mt[leader].main.quorumPeer.follower;
while (f == null || !f.isRunning()) {
if (sleepTime > LEADER_TIMEOUT_MS * 2) {
fail("Took too long for old leader to time out " + servers.mt[leader].main.quorumPeer.getPeerState());
}
Thread.sleep(100);
sleepTime += 100;
f = servers.mt[leader].main.quorumPeer.follower;
}
int newLeader = servers.findLeader();
// make sure a different leader was elected
assertNotEquals(leader, newLeader);
// 7. restart the previous leader to force it to replay the edits and possibly come up in a bad state
servers.mt[leader].shutdown();
servers.mt[leader].start();
// old client session can expire, restart it
servers.restartClient(leader, this);
waitForAll(servers, States.CONNECTED);
// make sure everything is consistent
for (int i = 0; i < SERVER_COUNT; i++) {
assertNull(servers.zk[i].exists("/zk" + leader, false), "server " + i + " should not have /zk" + leader);
}
}
use of org.apache.zookeeper.server.quorum.Leader.Proposal in project zookeeper by apache.
the class LocalSessionRequestTest method validateRequestLog.
/**
* Walk through the target peer commmittedLog.
* @param sessionId
* @param peerId
*/
private void validateRequestLog(long sessionId, int peerId) {
String session = Long.toHexString(sessionId);
LOG.info("Searching for txn of session 0x " + session + " on peer " + peerId);
String peerType = peerId == qb.getLeaderIndex() ? "leader" : "follower";
QuorumPeer peer = qb.getPeerList().get(peerId);
ZKDatabase db = peer.getActiveServer().getZKDatabase();
for (Proposal p : db.getCommittedLog()) {
assertFalse(p.request.sessionId == sessionId, "Should not see " + Request.op2String(p.request.type) + " request from local session 0x" + session + " on the " + peerType);
}
}
use of org.apache.zookeeper.server.quorum.Leader.Proposal in project zookeeper by apache.
the class RestoreCommittedLogTest method testRestoreCommittedLog.
/**
* test the purge
* @throws Exception an exception might be thrown here
*/
@Test
public void testRestoreCommittedLog() throws Exception {
File tmpDir = ClientBase.createTmpDir();
ClientBase.setupTestEnv();
ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000);
SyncRequestProcessor.setSnapCount(100);
final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]);
ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1);
f.startup(zks);
Assert.assertTrue("waiting for server being up ", ClientBase.waitForServerUp(HOSTPORT, CONNECTION_TIMEOUT));
ZooKeeper zk = ClientBase.createZKClient(HOSTPORT);
try {
for (int i = 0; i < 2000; i++) {
zk.create("/invalidsnap-" + i, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
} finally {
zk.close();
}
f.shutdown();
zks.shutdown();
Assert.assertTrue("waiting for server to shutdown", ClientBase.waitForServerDown(HOSTPORT, CONNECTION_TIMEOUT));
// start server again
zks = new ZooKeeperServer(tmpDir, tmpDir, 3000);
zks.startdata();
List<Proposal> committedLog = zks.getZKDatabase().getCommittedLog();
int logsize = committedLog.size();
LOG.info("committedLog size = {}", logsize);
Assert.assertTrue("log size != 0", (logsize != 0));
zks.shutdown();
}
use of org.apache.zookeeper.server.quorum.Leader.Proposal in project zookeeper by apache.
the class ZKDatabase method getCommittedLog.
public synchronized Collection<Proposal> getCommittedLog() {
final Collection<Proposal> result;
ReadLock rl = logLock.readLock();
// make a copy if this thread is not already holding a lock
if (logLock.getReadHoldCount() > 0) {
result = this.committedLog;
} else {
rl.lock();
try {
result = new ArrayList<>(this.committedLog);
} finally {
rl.unlock();
}
}
return Collections.unmodifiableCollection(result);
}
use of org.apache.zookeeper.server.quorum.Leader.Proposal in project zookeeper by apache.
the class TxnLogProposalIterator method next.
/**
* Proposal returned by this iterator has request part set to null, since
* it is not used for follower sync-up.
*/
@Override
public Proposal next() {
Proposal p = new Proposal();
try {
byte[] serializedData = Util.marshallTxnEntry(itr.getHeader(), itr.getTxn(), itr.getDigest());
QuorumPacket pp = new QuorumPacket(Leader.PROPOSAL, itr.getHeader().getZxid(), serializedData, null);
p.packet = pp;
p.request = null;
// This is the only place that can throw IO exception
hasNext = itr.next();
} catch (IOException e) {
LOG.error("Unable to read txnlog from disk", e);
hasNext = false;
}
return p;
}
Aggregations