/**
   * Handles paxos prepare messages
   *
   * @param msg the incomming message
   * @return a response message
   */
  public FleaseMessage handlePREPARE(FleaseMessage msg) {

    final FleaseAcceptorCell cc = getCell(msg);
    cc.touch();

    if ((cc.getPrepared() != null) && (cc.getPrepared().after(msg))) {
      if (Logging.isDebug() && config.isDebugPrintMessages()) {
        final String preped =
            (cc.getPrepared() == null)
                ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString()
                : cc.getPrepared().getProposalNo().toString();
        Logging.logMessage(
            Logging.LEVEL_DEBUG,
            Category.replication,
            this,
            "A prepare NACK p:" + preped + " is after " + msg.getProposalNo() + "");
      }
      FleaseMessage reject = new FleaseMessage(FleaseMessage.MsgType.MSG_PREPARE_NACK, msg);
      reject.setPrevProposalNo(cc.getPrepared().getProposalNo());
      reject.setLeaseHolder(null);
      reject.setLeaseTimeout(0);
      reject.setSendTimestamp(TimeSync.getGlobalTime());
      return reject;
    } else {
      if (Logging.isDebug() && config.isDebugPrintMessages()) {
        final String preped =
            (cc.getPrepared() == null)
                ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString()
                : cc.getPrepared().getProposalNo().toString();
        final String acced =
            (cc.getAccepted() == null)
                ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString()
                : cc.getAccepted().getProposalNo()
                    + "="
                    + cc.getAccepted().getLeaseHolder()
                    + "/"
                    + cc.getAccepted().getLeaseTimeout();
        Logging.logMessage(
            Logging.LEVEL_DEBUG,
            Category.replication,
            this,
            "A prepare ACK  p:" + preped + " -> " + msg.getProposalNo() + " a:" + acced);
      }
      // lastPrepared = msg;
      cc.setPrepared(msg);
      // FIXME:Persistently write to disk
      FleaseMessage response = new FleaseMessage(FleaseMessage.MsgType.MSG_PREPARE_ACK, msg);

      if (cc.getAccepted() != null) {

        response.setPrevProposalNo(cc.getAccepted().getProposalNo());
        response.setLeaseHolder(cc.getAccepted().getLeaseHolder());
        assert (response.getLeaseHolder() != null);
        response.setLeaseTimeout(cc.getAccepted().getLeaseTimeout());
      }
      response.setSendTimestamp(TimeSync.getGlobalTime());
      return response;
    }
  }
  /**
   * Handles paxos accept (vote) messages.
   *
   * @param msg incomming message
   * @return a response message or null
   */
  public FleaseMessage handleACCEPT(FleaseMessage msg) {

    final FleaseAcceptorCell cc = getCell(msg);

    cc.touch();
    if ((cc.getPrepared() != null) && (cc.getPrepared().after(msg))) {
      // reject the request
      if (Logging.isDebug() && config.isDebugPrintMessages()) {
        final String preped =
            (cc.getPrepared() == null)
                ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString()
                : cc.getPrepared().getProposalNo().toString();
        Logging.logMessage(
            Logging.LEVEL_DEBUG,
            Category.replication,
            this,
            "A accept  NACK p:" + preped + " is after " + msg.getProposalNo() + "");
      }
      FleaseMessage tmp = new FleaseMessage(FleaseMessage.MsgType.MSG_ACCEPT_NACK, msg);
      tmp.setSendTimestamp(TimeSync.getGlobalTime());
      tmp.setLeaseHolder(null);
      tmp.setLeaseTimeout(0);
      tmp.setPrevProposalNo(cc.getPrepared().getProposalNo());
      return tmp;
    } else {
      // okay accept it
      if (Logging.isDebug() && config.isDebugPrintMessages()) {
        final String preped =
            (cc.getPrepared() == null)
                ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString()
                : cc.getPrepared().getProposalNo().toString();
        final String acced =
            (cc.getAccepted() == null)
                ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString()
                : cc.getAccepted().getProposalNo()
                    + "="
                    + cc.getAccepted().getLeaseHolder()
                    + "/"
                    + cc.getAccepted().getLeaseTimeout();
        Logging.logMessage(
            Logging.LEVEL_DEBUG,
            Category.replication,
            this,
            "A accept  ACK  p:"
                + preped
                + " a: "
                + acced
                + " -> "
                + msg.getProposalNo()
                + "="
                + msg.getLeaseHolder()
                + "/"
                + msg.getLeaseTimeout());
      }
      assert (msg.getLeaseHolder() != null);
      cc.setAccepted(msg);
      cc.setPrepared(msg);

      FleaseMessage tmp = new FleaseMessage(FleaseMessage.MsgType.MSG_ACCEPT_ACK, msg);
      tmp.setSendTimestamp(TimeSync.getGlobalTime());
      return tmp;
    }
  }