コード例 #1
0
  private boolean updateCurrent(LeaderElection req) {
    boolean isNew = false;

    if (current == null) {
      current = new ElectionState();
      isNew = true;
    } else {
      if (req.getExpires() > current.maxDuration) {
        isNew = false; // If this election was started after the current election, dont do anything!
        logger.info("Ignoring this election - older election already in progress! Not voting!");
        return isNew;
      } else {
        isNew = true;
      }
    }

    if (req.getCandidateId() == this.nodeId) {
      // logger.info("Updating election details in RAFT Election");
      isNew = false;
    }

    current.electionID = req.getElectId();
    current.candidate = req.getCandidateId();
    current.desc = req.getDesc();
    current.maxDuration = req.getExpires();
    current.startedOn = System.currentTimeMillis();
    current.state = req.getAction();
    current.id = -1; // TODO me or sender?
    current.active = true;

    return isNew;
  }
コード例 #2
0
  /** @param args */
  public void processRequest(Management mgmt) {
    if (!mgmt.hasElection()) return;

    LeaderElection req = mgmt.getElection();

    // when a new node joins the network it will want to know who the leader
    // is - we kind of ram this request-response in the process request
    // though there has to be a better place for it
    if (req.getAction().getNumber() == LeaderElection.ElectAction.WHOISTHELEADER_VALUE) {
      respondToWhoIsTheLeader(mgmt);
      return;
    } else if (req.getAction().getNumber() == LeaderElection.ElectAction.THELEADERIS_VALUE) {
      logger.info(
          "Node "
              + conf.getNodeId()
              + " got an answer on who the leader is. Its Node "
              + req.getCandidateId());
      this.leaderNode = req.getCandidateId();
      this.termId = req.getTermId();
      // the current term id
      // TODO Last log index to be synced
      return;
    }

    // else fall through to an election
    // if the time has expired, an election is initiated.
    if (req.hasExpires()) {
      long ct = System.currentTimeMillis();
      if (ct > req.getExpires()) {
        // ran out of time so the election is over
        if (election != null) election.clear();
        return;
      }
    }

    Management rtn = electionInstance().process(mgmt);
    if (rtn != null) ConnectionManager.broadcast(rtn);
  }
コード例 #3
0
  /*
   * (non-Javadoc)
   *
   * @see poke.server.election.Election#process(eye.Comm.LeaderElection)
   *
   * @return The Management instance returned represents the message to send
   * on. If null, no action is required. Not a great choice to convey to the
   * caller; can be improved upon easily.
   */
  @Override
  public Management process(Management mgmt) {
    if (!mgmt.hasElection()) return null;

    LeaderElection req = mgmt.getElection();
    if (req.getExpires() <= System.currentTimeMillis()) {
      // election has expired without a conclusion?
    }

    Management rtn = null;

    if (req.getAction().getNumber() == ElectAction.DECLAREELECTION_VALUE) {
      // an election is declared!

      // required to eliminate duplicate messages - on a declaration,
      // should not happen if the network does not have cycles
      List<VectorClock> rtes = mgmt.getHeader().getPathList();
      for (VectorClock rp : rtes) {
        if (rp.getNodeId() == this.nodeId) {
          // message has already been sent to me, don't use and
          // forward
          return null;
        }
      }

      // I got here because the election is unknown to me

      // this 'if debug is on' should cover the below dozen or so
      // println()s. It is here to help with seeing when an election
      // occurs.
      if (logger.isDebugEnabled()) {}

      System.out.println("\n\n*********************************************************");
      System.out.println("   RAFT ELECTION: Election declared");
      System.out.println("   Election ID:  " + req.getElectId());
      System.out.println("   Rcv from:     Node " + mgmt.getHeader().getOriginator());
      System.out.println("   Expires:      " + new Date(req.getExpires()));
      System.out.println("   Nominates:    Node " + req.getCandidateId());
      System.out.println("   Desc:         " + req.getDesc());
      System.out.print("   Routing tbl:  [");
      for (VectorClock rp : rtes)
        System.out.print(
            "Node " + rp.getNodeId() + " (" + rp.getVersion() + "," + rp.getTime() + "), ");
      System.out.println("]");
      System.out.println("*********************************************************\n\n");

      // sync master IDs to current election
      ElectionIDGenerator.setMasterID(req.getElectId());

      /**
       * a new election can be declared over an existing election.
       *
       * <p>TODO need to have an monotonically increasing ID that we can test
       */
      boolean isNew = updateCurrent(req);
      rtn = castVote(mgmt, isNew);

    } else if (req.getAction().getNumber() == ElectAction.DECLAREVOID_VALUE) {
      // no one was elected, I am dropping into standby mode
      logger.info("TODO: no one was elected, I am dropping into standby mode");
      this.clear();
      notify(false, null);
    } else if (req.getAction().getNumber() == ElectAction.DECLAREWINNER_VALUE) {
      // some node declared itself the leader
      logger.info(
          "Election "
              + req.getElectId()
              + ": Node "
              + req.getCandidateId()
              + " is declared the leader");
      updateCurrent(mgmt.getElection());
      current.active = false; // it's over
      notify(true, req.getCandidateId());
    } else if (req.getAction().getNumber() == ElectAction.ABSTAIN_VALUE) {
      // for some reason, a node declines to vote - therefore, do nothing
    } else if (req.getAction().getNumber() == ElectAction.NOMINATE_VALUE) {
      boolean isNew = updateCurrent(mgmt.getElection());
      rtn = castVote(mgmt, isNew);
    } else {
      // this is me!
    }

    return rtn;
  }