Ejemplo n.º 1
0
  private ElectionResult countVotes(
      HashMap<InetSocketAddress, Vote> votes, HashSet<Long> heardFrom) {
    ElectionResult result = new ElectionResult();
    // Initialize with null vote
    result.vote = new Vote(Long.MIN_VALUE, Long.MIN_VALUE);
    result.winner = new Vote(Long.MIN_VALUE, Long.MIN_VALUE);
    Collection<Vote> votesCast = votes.values();
    // First make the views consistent. Sometimes peers will have
    // different zxids for a server depending on timing.
    for (Iterator<Vote> i = votesCast.iterator(); i.hasNext(); ) {
      Vote v = i.next();
      if (!heardFrom.contains(v.id)) {
        // Discard votes for machines that we didn't hear from
        i.remove();
        continue;
      }
      for (Vote w : votesCast) {
        if (v.id == w.id) {
          if (v.zxid < w.zxid) {
            v.zxid = w.zxid;
          }
        }
      }
    }

    HashMap<Vote, Integer> countTable = new HashMap<Vote, Integer>();
    // Now do the tally
    for (Vote v : votesCast) {
      Integer count = countTable.get(v);
      if (count == null) {
        count = Integer.valueOf(0);
      }
      countTable.put(v, count + 1);
      if (v.id == result.vote.id) {
        result.count++;
      } else if (v.zxid > result.vote.zxid
          || (v.zxid == result.vote.zxid && v.id > result.vote.id)) {
        result.vote = v;
        result.count = 1;
      }
    }
    result.winningCount = 0;
    LOG.info("Election tally: ");
    for (Entry<Vote, Integer> entry : countTable.entrySet()) {
      if (entry.getValue() > result.winningCount) {
        result.winningCount = entry.getValue();
        result.winner = entry.getKey();
      }
      LOG.info(entry.getKey().id + "\t-> " + entry.getValue());
    }
    return result;
  }
 private void leaveInstance(Vote v) {
   if (LOG.isDebugEnabled()) {
     LOG.debug(
         "About to leave FLE instance: leader="
             + v.getId()
             + ", zxid=0x"
             + Long.toHexString(v.getZxid())
             + ", my id="
             + self.getId()
             + ", my state="
             + self.getPeerState());
   }
   recvqueue.clear();
 }
  /**
   * Termination predicate. Given a set of votes, determines if have sufficient to declare the end
   * of the election round.
   *
   * @param votes Set of votes
   * @param l Identifier of the vote received last
   * @param zxid zxid of the the vote received last
   */
  protected boolean termPredicate(HashMap<Long, Vote> votes, Vote vote) {

    HashSet<Long> set = new HashSet<Long>();

    /*
     * First make the views consistent. Sometimes peers will have different
     * zxids for a server depending on timing.
     */
    for (Map.Entry<Long, Vote> entry : votes.entrySet()) {
      if (vote.equals(entry.getValue())) {
        set.add(entry.getKey());
      }
    }

    return self.getQuorumVerifier().containsQuorum(set);
  }
      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");
      }