package com.techq.available.rubbish; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.techq.available.AvailableConfig; import com.techq.available.quorum.Election; import com.techq.available.quorum.Notification; import com.techq.available.quorum.Notification.mType; public class FollowerHandler3 { private static final Logger LOG = LoggerFactory.getLogger(FollowerHandler3.class); volatile boolean confirmed = false; int tick = 0; Election election; long leaderId = -1; ConfirmWorker worker; boolean hasStartWork = false; AtomicLong expectClock = new AtomicLong(0); public FollowerHandler3(Election election, long leaderId) { super(); this.election = election; this.leaderId = leaderId; worker = new ConfirmWorker(election); } public boolean followLeader(Notification n) throws InterruptedException { n.setLogicalClock(expectClock.addAndGet(1)); if (!hasStartWork) { hasStartWork = true; worker.start(); } sendAgree(n); confirmed = false; tick = 0; worker.startPolling(); while(!confirmed && tick <= AvailableConfig.syncTick) { TimeUnit.MILLISECONDS.sleep(AvailableConfig.tickTime); tick++; } worker.finishPolling(); if (tick <= AvailableConfig.syncTick && confirmed == true) { return true; } LOG.warn("can't receive any confirms!!, restart looking leader!!!"); return false; } private void sendAgree(Notification n) { election.offerACK(n); } class ConfirmWorker extends Thread { final Election election; volatile boolean finishPoll = false; volatile boolean isRunning = true; CyclicBarrier barrier = new CyclicBarrier(2); ConfirmWorker(Election election) { this.election = election; } public void run() { while(isRunning) { waiting(); try { finishPoll = false; while(!finishPoll) { Notification n = election.pollConfirm(AvailableConfig.pollTimeout, AvailableConfig.pollTimeUnit); if (n != null && n.getFrom() == leaderId && n.getType() == Notification.mType.CONFIRM && n.getLogicalClock() == expectClock.get()) { LOG.info("Got leader confirms"); finishPoll = true; confirmed = true; break; } else { /** if the ticket is not current, i will push back such ticket*/ election.pushback(n); } } LOG.info("finish polling!"); } catch (InterruptedException e) { LOG.error("interrupt when poll confirms from leader, error=", e); } } } private void waiting() { try { barrier.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (BrokenBarrierException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void finishWork() { this.isRunning = false; finishPolling(); } public void finishPolling() { if (this.finishPoll) { return; } this.finishPoll = true; this.interrupt(); } public void startPolling() { LOG.info("call start polling..."); //call again waiting(); } } }