Exemplo n.º 1
5
  @Test
  public void testCnxManagerTimeout() throws Exception {
    Random rand = new Random();
    byte b = (byte) rand.nextInt();
    int deadPort = PortAssignment.unique();
    String deadAddress = new String("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())));
    peerTmpdir[2] = ClientBase.createTmpDir();

    QuorumPeer peer =
        new QuorumPeer(peers, peerTmpdir[1], peerTmpdir[1], peerClientPort[1], 3, 1, 1000, 2, 2);
    QuorumCnxManager cnxManager = new QuorumCnxManager(peer);
    QuorumCnxManager.Listener listener = cnxManager.listener;
    if (listener != null) {
      listener.start();
    } else {
      LOG.error("Null listener when initializing cnx manager");
    }

    long begin = System.currentTimeMillis();
    cnxManager.toSend(new Long(2), createMsg(ServerState.LOOKING.ordinal(), 1, -1, 1));
    long end = System.currentTimeMillis();

    if ((end - begin) > 6000) fail("Waited more than necessary");
  }
Exemplo n.º 2
0
  @Test
  public void testCnxManager() throws Exception {
    CnxManagerThread thread = new CnxManagerThread();

    thread.start();

    QuorumPeer peer =
        new QuorumPeer(peers, peerTmpdir[1], peerTmpdir[1], peerClientPort[1], 3, 1, 1000, 2, 2);
    QuorumCnxManager cnxManager = new QuorumCnxManager(peer);
    QuorumCnxManager.Listener listener = cnxManager.listener;
    if (listener != null) {
      listener.start();
    } else {
      LOG.error("Null listener when initializing cnx manager");
    }

    cnxManager.toSend(new Long(0), createMsg(ServerState.LOOKING.ordinal(), 1, -1, 1));

    Message m = null;
    int numRetries = 1;
    while ((m == null) && (numRetries++ <= THRESHOLD)) {
      m = cnxManager.recvQueue.poll(3000, TimeUnit.MILLISECONDS);
      if (m == null) cnxManager.connectAll();
    }

    assertTrue("Exceeded number of retries", numRetries <= THRESHOLD);

    thread.join(5000);
    if (thread.isAlive()) {
      fail("Thread didn't join");
    } else {
      if (thread.failed) fail("Did not receive expected message");
    }
  }
Exemplo n.º 3
0
  /**
   * Tests a bug in QuorumCnxManager that causes a spin lock when a negative value is sent. This
   * test checks if the connection is being closed upon a message with negative length.
   *
   * @throws Exception
   */
  @Test
  public void testCnxManagerSpinLock() throws Exception {
    QuorumPeer peer =
        new QuorumPeer(peers, peerTmpdir[1], peerTmpdir[1], peerClientPort[1], 3, 1, 1000, 2, 2);
    QuorumCnxManager cnxManager = new QuorumCnxManager(peer);
    QuorumCnxManager.Listener listener = cnxManager.listener;
    if (listener != null) {
      listener.start();
    } else {
      LOG.error("Null listener when initializing cnx manager");
    }

    int port = peers.get(peer.getId()).electionAddr.getPort();
    LOG.info("Election port: " + port);
    InetSocketAddress addr = new InetSocketAddress(port);

    Thread.sleep(1000);

    SocketChannel sc = SocketChannel.open();
    sc.socket().connect(peers.get(new Long(1)).electionAddr, 5000);

    /*
     * Write id first then negative length.
     */
    byte[] msgBytes = new byte[8];
    ByteBuffer msgBuffer = ByteBuffer.wrap(msgBytes);
    msgBuffer.putLong(new Long(2));
    msgBuffer.position(0);
    sc.write(msgBuffer);

    msgBuffer = ByteBuffer.wrap(new byte[4]);
    msgBuffer.putInt(-20);
    msgBuffer.position(0);
    sc.write(msgBuffer);

    Thread.sleep(1000);

    try {
      /*
       * Write a number of times until it
       * detects that the socket is broken.
       */
      for (int i = 0; i < 100; i++) {
        msgBuffer.position(0);
        sc.write(msgBuffer);
      }
      fail("Socket has not been closed");
    } catch (Exception e) {
      LOG.info("Socket has been closed as expected");
    }
    peer.shutdown();
    cnxManager.halt();
  }
 public void shutdown() {
   stop = true;
   LOG.debug("Shutting down connection manager");
   manager.halt();
   LOG.debug("Shutting down messenger");
   messenger.halt();
   LOG.debug("FLE is down");
 }
Exemplo n.º 5
0
 public String _verifyThreadCount(ArrayList<QuorumPeer> peerList, long ecnt) {
   for (int myid = 0; myid < peerList.size(); myid++) {
     QuorumPeer peer = peerList.get(myid);
     QuorumCnxManager cnxManager = peer.getQuorumCnxManager();
     long cnt = cnxManager.getThreadCount();
     if (cnt != ecnt) {
       return new String(
           new Date()
               + " Incorrect number of Worker threads for sid="
               + myid
               + " expected "
               + ecnt
               + " found "
               + cnt);
     }
   }
   return null;
 }
Exemplo n.º 6
0
    public void run() {
      try {
        QuorumPeer peer =
            new QuorumPeer(
                peers, peerTmpdir[0], peerTmpdir[0], peerClientPort[0], 3, 0, 1000, 2, 2);
        QuorumCnxManager cnxManager = new QuorumCnxManager(peer);
        QuorumCnxManager.Listener listener = cnxManager.listener;
        if (listener != null) {
          listener.start();
        } else {
          LOG.error("Null listener when initializing cnx manager");
        }

        long sid = 1;
        cnxManager.toSend(sid, createMsg(ServerState.LOOKING.ordinal(), 0, -1, 1));

        Message m = null;
        int numRetries = 1;
        while ((m == null) && (numRetries++ <= THRESHOLD)) {
          m = cnxManager.recvQueue.poll(3000, TimeUnit.MILLISECONDS);
          if (m == null) cnxManager.connectAll();
        }

        if (numRetries > THRESHOLD) {
          failed = true;
          return;
        }

        cnxManager.testInitiateConnection(sid);

        m = cnxManager.recvQueue.poll(3000, TimeUnit.MILLISECONDS);
        if (m == null) {
          failed = true;
          return;
        }
      } catch (Exception e) {
        LOG.error("Exception while running mock thread", e);
        fail("Unexpected exception");
      }
    }
  /** 寻找对应的leader */
  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;
    }
    if (self.start_fle == 0) {
      self.start_fle = System.currentTimeMillis();
    }
    try {
      HashMap<Long, Vote> recvset = new HashMap<Long, Vote>();

      HashMap<Long, Vote> outofelection = new HashMap<Long, Vote>();

      int notTimeout = finalizeWait;

      synchronized (this) {
        logicalclock++;
        updateProposal(getInitId(), getInitLastLoggedZxid(), getPeerEpoch());
      }

      LOG.info(
          "New election. My id =  "
              + self.getId()
              + ", proposed zxid=0x"
              + Long.toHexString(proposedZxid));
      sendNotifications();

      /*
       * Loop in which we exchange notifications until we find a leader
       */

      while ((self.getPeerState() == ServerState.LOOKING) && (!stop)) {
        /*
         * Remove next notification from queue, times out after 2 times
         * the termination time
         */
        Notification n = recvqueue.poll(notTimeout, TimeUnit.MILLISECONDS);

        /*
         * Sends more notifications if haven't received enough.
         * Otherwise processes new notification.
         */
        if (n == null) {
          if (manager.haveDelivered()) {
            sendNotifications();
          } else {
            manager.connectAll();
          }

          /*
           * Exponential backoff
           */
          int tmpTimeOut = notTimeout * 2;
          notTimeout =
              (tmpTimeOut < maxNotificationInterval ? tmpTimeOut : maxNotificationInterval);
          LOG.info("Notification time out: " + notTimeout);
        } else if (self.getVotingView().containsKey(n.sid)) {
          /*
           * Only proceed if the vote comes from a replica in the
           * voting view.
           */
          switch (n.state) {
            case LOOKING:
              // If notification > current, replace and send messages
              // out
              if (n.electionEpoch > logicalclock) {
                logicalclock = n.electionEpoch;
                recvset.clear();
                if (totalOrderPredicate(
                    n.leader,
                    n.zxid,
                    n.peerEpoch,
                    getInitId(),
                    getInitLastLoggedZxid(),
                    getPeerEpoch())) {
                  updateProposal(n.leader, n.zxid, n.peerEpoch);
                } else {
                  updateProposal(getInitId(), getInitLastLoggedZxid(), getPeerEpoch());
                }
                sendNotifications();
              } else if (n.electionEpoch < logicalclock) {
                if (LOG.isDebugEnabled()) {
                  LOG.debug(
                      "Notification election epoch is smaller than logicalclock. n.electionEpoch = 0x"
                          + Long.toHexString(n.electionEpoch)
                          + ", logicalclock=0x"
                          + Long.toHexString(logicalclock));
                }
                break;
              } else if (totalOrderPredicate(
                  n.leader, n.zxid, n.peerEpoch, proposedLeader, proposedZxid, proposedEpoch)) {
                updateProposal(n.leader, n.zxid, n.peerEpoch);
                sendNotifications();
              }

              if (LOG.isDebugEnabled()) {
                LOG.debug(
                    "Adding vote: from="
                        + n.sid
                        + ", proposed leader="
                        + n.leader
                        + ", proposed zxid=0x"
                        + Long.toHexString(n.zxid)
                        + ", proposed election epoch=0x"
                        + Long.toHexString(n.electionEpoch));
              }

              recvset.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch));

              if (termPredicate(
                  recvset, new Vote(proposedLeader, proposedZxid, logicalclock, proposedEpoch))) {

                // Verify if there is any change in the proposed
                // leader
                while ((n = recvqueue.poll(finalizeWait, TimeUnit.MILLISECONDS)) != null) {
                  if (totalOrderPredicate(
                      n.leader, n.zxid, n.peerEpoch, proposedLeader, proposedZxid, proposedEpoch)) {
                    recvqueue.put(n);
                    break;
                  }
                }

                /*
                 * This predicate is true once we don't read any new
                 * relevant message from the reception queue
                 */
                if (n == null) {
                  self.setPeerState(
                      (proposedLeader == self.getId()) ? ServerState.LEADING : learningState());

                  Vote endVote =
                      new Vote(proposedLeader, proposedZxid, logicalclock, proposedEpoch);
                  leaveInstance(endVote);
                  return endVote;
                }
              }
              break;
            case OBSERVING:
              LOG.debug("Notification from observer: " + n.sid);
              break;
            case FOLLOWING:
            case LEADING:
              /*
               * Consider all notifications from the same epoch
               * together.
               */
              if (n.electionEpoch == logicalclock) {
                recvset.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch));

                if (ooePredicate(recvset, outofelection, n)) {
                  self.setPeerState(
                      (n.leader == self.getId()) ? ServerState.LEADING : learningState());

                  Vote endVote = new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch);
                  leaveInstance(endVote);
                  return endVote;
                }
              }

              /*
               * Before joining an established ensemble, verify a
               * majority is following the same leader.
               */
              outofelection.put(
                  n.sid,
                  new Vote(n.version, n.leader, n.zxid, n.electionEpoch, n.peerEpoch, n.state));

              if (ooePredicate(outofelection, outofelection, n)) {
                synchronized (this) {
                  logicalclock = n.electionEpoch;
                  self.setPeerState(
                      (n.leader == self.getId()) ? ServerState.LEADING : learningState());
                }
                Vote endVote = new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch);
                leaveInstance(endVote);
                return endVote;
              }
              break;
            default:
              LOG.warn("Notification state unrecognized: {} (n.state), {} (n.sid)", n.state, n.sid);
              break;
          }
        } else {
          LOG.warn("Ignoring notification from non-cluster member " + n.sid);
        }
      }
      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;
    }
  }
 /**
  * Called by run() once there is a new message to send.
  *
  * @param m message to send
  */
 void process(ToSend m) {
   ByteBuffer requestBuffer =
       buildMsg(m.state.ordinal(), m.leader, m.zxid, m.electionEpoch, m.peerEpoch);
   manager.toSend(m.sid, requestBuffer);
 }
      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");
      }