use of org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer in project zookeeper by apache.
the class LeaderElection method lookForLeader.
/**
* Invoked in QuorumPeer to find or elect a new leader.
*
* @throws InterruptedException
*/
public Vote lookForLeader() throws InterruptedException {
try {
self.jmxLeaderElectionBean = new LeaderElectionBean();
MBeanRegistry.getInstance().register(self.jmxLeaderElectionBean, self.jmxLocalPeerBean);
} catch (Exception e) {
LOG.warn("Failed to register with JMX", e);
self.jmxLeaderElectionBean = null;
}
try {
self.setCurrentVote(new Vote(self.getId(), self.getLastLoggedZxid()));
// We are going to look for a leader by casting a vote for ourself
byte[] requestBytes = new byte[4];
ByteBuffer requestBuffer = ByteBuffer.wrap(requestBytes);
byte[] responseBytes = new byte[28];
ByteBuffer responseBuffer = ByteBuffer.wrap(responseBytes);
/* The current vote for the leader. Initially me! */
DatagramSocket s = null;
try {
s = new DatagramSocket();
s.setSoTimeout(200);
} catch (SocketException e1) {
LOG.error("Socket exception when creating socket for leader election", e1);
System.exit(4);
}
DatagramPacket requestPacket = new DatagramPacket(requestBytes, requestBytes.length);
DatagramPacket responsePacket = new DatagramPacket(responseBytes, responseBytes.length);
int xid = epochGen.nextInt();
while (self.isRunning()) {
HashMap<InetSocketAddress, Vote> votes = new HashMap<InetSocketAddress, Vote>(self.getVotingView().size());
requestBuffer.clear();
requestBuffer.putInt(xid);
requestPacket.setLength(4);
HashSet<Long> heardFrom = new HashSet<Long>();
for (QuorumServer server : self.getVotingView().values()) {
LOG.info("Server address: " + server.addr);
try {
requestPacket.setSocketAddress(server.addr);
} catch (IllegalArgumentException e) {
// in order to capture this critical detail.
throw new IllegalArgumentException("Unable to set socket address on packet, msg:" + e.getMessage() + " with addr:" + server.addr, e);
}
try {
s.send(requestPacket);
responsePacket.setLength(responseBytes.length);
s.receive(responsePacket);
if (responsePacket.getLength() != responseBytes.length) {
LOG.error("Got a short response: " + responsePacket.getLength());
continue;
}
responseBuffer.clear();
int recvedXid = responseBuffer.getInt();
if (recvedXid != xid) {
LOG.error("Got bad xid: expected " + xid + " got " + recvedXid);
continue;
}
long peerId = responseBuffer.getLong();
heardFrom.add(peerId);
//if(server.id != peerId){
Vote vote = new Vote(responseBuffer.getLong(), responseBuffer.getLong());
InetSocketAddress addr = (InetSocketAddress) responsePacket.getSocketAddress();
votes.put(addr, vote);
//}
} catch (IOException e) {
LOG.warn("Ignoring exception while looking for leader", e);
// Errors are okay, since hosts may be
// down
}
}
ElectionResult result = countVotes(votes, heardFrom);
// for a dead peer
if (result.numValidVotes == 0) {
self.setCurrentVote(new Vote(self.getId(), self.getLastLoggedZxid()));
} else {
if (result.winner.getId() >= 0) {
self.setCurrentVote(result.vote);
// To do: this doesn't use a quorum verifier
if (result.winningCount > (self.getVotingView().size() / 2)) {
self.setCurrentVote(result.winner);
s.close();
Vote current = self.getCurrentVote();
LOG.info("Found leader: my type is: " + self.getLearnerType());
/*
* We want to make sure we implement the state machine
* correctly. If we are a PARTICIPANT, once a leader
* is elected we can move either to LEADING or
* FOLLOWING. However if we are an OBSERVER, it is an
* error to be elected as a Leader.
*/
if (self.getLearnerType() == LearnerType.OBSERVER) {
if (current.getId() == self.getId()) {
// This should never happen!
LOG.error("OBSERVER elected as leader!");
Thread.sleep(100);
} else {
self.setPeerState(ServerState.OBSERVING);
Thread.sleep(100);
return current;
}
} else {
self.setPeerState((current.getId() == self.getId()) ? ServerState.LEADING : ServerState.FOLLOWING);
if (self.getPeerState() == ServerState.FOLLOWING) {
Thread.sleep(100);
}
return current;
}
}
}
}
Thread.sleep(1000);
}
return null;
} finally {
try {
if (self.jmxLeaderElectionBean != null) {
MBeanRegistry.getInstance().unregister(self.jmxLeaderElectionBean);
}
} catch (Exception e) {
LOG.warn("Failed to unregister with JMX", e);
}
self.jmxLeaderElectionBean = null;
}
}
use of org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer in project zookeeper by apache.
the class CnxManagerTest method testCnxManagerTimeout.
@Test
public void testCnxManagerTimeout() throws Exception {
Random rand = new Random();
byte b = (byte) rand.nextInt();
int deadPort = PortAssignment.unique();
String deadAddress = "10.1.1." + b;
LOG.info("This is the dead address I'm trying: " + deadAddress);
peers.put(Long.valueOf(2), new QuorumServer(2, new InetSocketAddress(deadAddress, deadPort), new InetSocketAddress(deadAddress, PortAssignment.unique()), new InetSocketAddress(deadAddress, PortAssignment.unique())));
peerTmpdir[2] = ClientBase.createTmpDir();
QuorumPeer peer = new QuorumPeer(peers, peerTmpdir[1], peerTmpdir[1], peerClientPort[1], 3, 1, 1000, 2, 2);
QuorumCnxManager cnxManager = peer.createCnxnManager();
QuorumCnxManager.Listener listener = cnxManager.listener;
if (listener != null) {
listener.start();
} else {
LOG.error("Null listener when initializing cnx manager");
}
long begin = Time.currentElapsedTime();
cnxManager.toSend(2L, createMsg(ServerState.LOOKING.ordinal(), 1, -1, 1));
long end = Time.currentElapsedTime();
if ((end - begin) > 6000)
Assert.fail("Waited more than necessary");
cnxManager.halt();
Assert.assertFalse(cnxManager.listener.isAlive());
}
use of org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer in project rest.li by linkedin.
the class ZKQuorum method createNewPeerData.
private void createNewPeerData(int id) {
int clientPort = ZKTestUtil.getRandomPort();
int quorumPort = ZKTestUtil.getRandomPort() + 1000;
int electionPort = ZKTestUtil.getRandomPort() + 1001;
ZKPeer zkpeer = new ZKPeer(id, ZKTestUtil.createTempDir("zkdata" + id), ZKTestUtil.createTempDir("zklog" + id), HOST, clientPort, quorumPort, electionPort);
_peers.put(id, zkpeer);
_peersView.put(Long.valueOf(id), new QuorumServer(id, HOST, quorumPort, electionPort, LearnerType.PARTICIPANT));
_log.info("Created peer #" + id + " with ports:" + clientPort + "/" + quorumPort + "/" + electionPort + " peer server addr:" + _peersView.get(Long.valueOf(id)).addr + " peer server electionAddr:" + _peersView.get(Long.valueOf(id)).electionAddr);
}
use of org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer in project zookeeper by apache.
the class Observer method findLearnerMaster.
private QuorumServer findLearnerMaster() {
QuorumPeer.QuorumServer prescribedLearnerMaster = nextLearnerMaster.getAndSet(null);
if (prescribedLearnerMaster != null && self.validateLearnerMaster(Long.toString(prescribedLearnerMaster.id)) == null) {
LOG.warn("requested next learner master {} is no longer valid", prescribedLearnerMaster);
prescribedLearnerMaster = null;
}
final QuorumPeer.QuorumServer master = (prescribedLearnerMaster == null) ? self.findLearnerMaster(findLeader()) : prescribedLearnerMaster;
currentLearnerMaster = master;
if (master == null) {
LOG.warn("No learner master found");
} else {
LOG.info("Observing new leader sid={} addr={}", master.id, master.addr);
}
return master;
}
use of org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer in project zookeeper by apache.
the class Follower method followLeader.
/**
* the main method called by the follower to follow the leader
*
* @throws InterruptedException
*/
void followLeader() throws InterruptedException {
self.end_fle = Time.currentElapsedTime();
long electionTimeTaken = self.end_fle - self.start_fle;
self.setElectionTimeTaken(electionTimeTaken);
ServerMetrics.getMetrics().ELECTION_TIME.add(electionTimeTaken);
LOG.info("FOLLOWING - LEADER ELECTION TOOK - {} {}", electionTimeTaken, QuorumPeer.FLE_TIME_UNIT);
self.start_fle = 0;
self.end_fle = 0;
fzk.registerJMX(new FollowerBean(this, zk), self.jmxLocalPeerBean);
long connectionTime = 0;
boolean completedSync = false;
try {
self.setZabState(QuorumPeer.ZabState.DISCOVERY);
QuorumServer leaderServer = findLeader();
try {
connectToLeader(leaderServer.addr, leaderServer.hostname);
connectionTime = System.currentTimeMillis();
long newEpochZxid = registerWithLeader(Leader.FOLLOWERINFO);
if (self.isReconfigStateChange()) {
throw new Exception("learned about role change");
}
// check to see if the leader zxid is lower than ours
// this should never happen but is just a safety check
long newEpoch = ZxidUtils.getEpochFromZxid(newEpochZxid);
if (newEpoch < self.getAcceptedEpoch()) {
LOG.error("Proposed leader epoch " + ZxidUtils.zxidToString(newEpochZxid) + " is less than our accepted epoch " + ZxidUtils.zxidToString(self.getAcceptedEpoch()));
throw new IOException("Error: Epoch of leader is lower");
}
long startTime = Time.currentElapsedTime();
self.setLeaderAddressAndId(leaderServer.addr, leaderServer.getId());
self.setZabState(QuorumPeer.ZabState.SYNCHRONIZATION);
syncWithLeader(newEpochZxid);
self.setZabState(QuorumPeer.ZabState.BROADCAST);
completedSync = true;
long syncTime = Time.currentElapsedTime() - startTime;
ServerMetrics.getMetrics().FOLLOWER_SYNC_TIME.add(syncTime);
if (self.getObserverMasterPort() > 0) {
LOG.info("Starting ObserverMaster");
om = new ObserverMaster(self, fzk, self.getObserverMasterPort());
om.start();
} else {
om = null;
}
// create a reusable packet to reduce gc impact
QuorumPacket qp = new QuorumPacket();
while (this.isRunning()) {
readPacket(qp);
processPacket(qp);
}
} catch (Exception e) {
LOG.warn("Exception when following the leader", e);
closeSocket();
// clear pending revalidations
pendingRevalidations.clear();
}
} finally {
if (om != null) {
om.stop();
}
zk.unregisterJMX(this);
if (connectionTime != 0) {
long connectionDuration = System.currentTimeMillis() - connectionTime;
LOG.info("Disconnected from leader (with address: {}). Was connected for {}ms. Sync state: {}", leaderAddr, connectionDuration, completedSync);
messageTracker.dumpToLog(leaderAddr.toString());
}
}
}
Aggregations