public void run() {

        Message response;
        while (!stop) {
          // Sleeps on receive
          try {
            response = manager.pollRecvQueue(3000, TimeUnit.MILLISECONDS);
            if (response == null) continue;

            /*
             * If it is from an observer, respond right away. Note
             * that the following predicate assumes that if a server
             * is not a follower, then it must be an observer. If we
             * ever have any other type of learner in the future,
             * we'll have to change the way we check for observers.
             */
            if (!self.getVotingView().containsKey(response.sid)) {
              Vote current = self.getCurrentVote();
              ToSend notmsg =
                  new ToSend(
                      ToSend.mType.notification,
                      current.getId(),
                      current.getZxid(),
                      logicalclock,
                      self.getPeerState(),
                      response.sid,
                      current.getPeerEpoch());

              sendqueue.offer(notmsg);
            } else {
              // Receive new message
              if (LOG.isDebugEnabled()) {
                LOG.debug("Receive new notification message. My id = " + self.getId());
              }

              /*
               * We check for 28 bytes for backward compatibility
               */
              if (response.buffer.capacity() < 28) {
                LOG.error("Got a short response: " + response.buffer.capacity());
                continue;
              }
              boolean backCompatibility = (response.buffer.capacity() == 28);
              response.buffer.clear();

              // Instantiate Notification and set its attributes
              Notification n = new Notification();

              // State of peer that sent this message
              QuorumPeer.ServerState ackstate = QuorumPeer.ServerState.LOOKING;
              switch (response.buffer.getInt()) {
                case 0:
                  ackstate = QuorumPeer.ServerState.LOOKING;
                  break;
                case 1:
                  ackstate = QuorumPeer.ServerState.FOLLOWING;
                  break;
                case 2:
                  ackstate = QuorumPeer.ServerState.LEADING;
                  break;
                case 3:
                  ackstate = QuorumPeer.ServerState.OBSERVING;
                  break;
                default:
                  continue;
              }

              n.leader = response.buffer.getLong();
              n.zxid = response.buffer.getLong();
              n.electionEpoch = response.buffer.getLong();
              n.state = ackstate;
              n.sid = response.sid;
              if (!backCompatibility) {
                n.peerEpoch = response.buffer.getLong();
              } else {
                if (LOG.isInfoEnabled()) {
                  LOG.info("Backward compatibility mode, server id=" + n.sid);
                }
                n.peerEpoch = ZxidUtils.getEpochFromZxid(n.zxid);
              }

              /*
               * Version added in 3.4.6
               */

              n.version = (response.buffer.remaining() >= 4) ? response.buffer.getInt() : 0x0;

              /*
               * Print notification info
               */
              if (LOG.isInfoEnabled()) {
                printNotification(n);
              }

              /*
               * If this server is looking, then send proposed
               * leader
               */

              if (self.getPeerState() == QuorumPeer.ServerState.LOOKING) {
                recvqueue.offer(n);

                /*
                 * Send a notification back if the peer that
                 * sent this message is also looking and its
                 * logical clock is lagging behind.
                 */
                if ((ackstate == QuorumPeer.ServerState.LOOKING)
                    && (n.electionEpoch < logicalclock)) {
                  Vote v = getVote();
                  ToSend notmsg =
                      new ToSend(
                          ToSend.mType.notification,
                          v.getId(),
                          v.getZxid(),
                          logicalclock,
                          self.getPeerState(),
                          response.sid,
                          v.getPeerEpoch());
                  sendqueue.offer(notmsg);
                }
              } else {
                /*
                 * If this server is not looking, but the one
                 * that sent the ack is looking, then send back
                 * what it believes to be the leader.
                 */
                Vote current = self.getCurrentVote();
                if (ackstate == QuorumPeer.ServerState.LOOKING) {
                  if (LOG.isDebugEnabled()) {
                    LOG.debug(
                        "Sending new notification. My id =  "
                            + self.getId()
                            + " recipient="
                            + response.sid
                            + " zxid=0x"
                            + Long.toHexString(current.getZxid())
                            + " leader="
                            + current.getId());
                  }

                  ToSend notmsg;
                  if (n.version > 0x0) {
                    notmsg =
                        new ToSend(
                            ToSend.mType.notification,
                            current.getId(),
                            current.getZxid(),
                            current.getElectionEpoch(),
                            self.getPeerState(),
                            response.sid,
                            current.getPeerEpoch());

                  } else {
                    Vote bcVote = self.getBCVote();
                    notmsg =
                        new ToSend(
                            ToSend.mType.notification,
                            bcVote.getId(),
                            bcVote.getZxid(),
                            bcVote.getElectionEpoch(),
                            self.getPeerState(),
                            response.sid,
                            bcVote.getPeerEpoch());
                  }
                  sendqueue.offer(notmsg);
                }
              }
            }
          } catch (InterruptedException e) {
            System.out.println(
                "Interrupted Exception while waiting for new message" + e.toString());
          }
        }
        LOG.info("WorkerReceiver is down");
      }