@Override
 public int hashCode() {
   int result = pendingValues != null ? pendingValues.hashCode() : 0;
   result = 31 * result + (bookedInstances != null ? bookedInstances.hashCode() : 0);
   result = 31 * result + (paxosInstances != null ? paxosInstances.hashCode() : 0);
   return result;
 }
  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }

    ProposerContextImpl that = (ProposerContextImpl) o;

    if (bookedInstances != null
        ? !bookedInstances.equals(that.bookedInstances)
        : that.bookedInstances != null) {
      return false;
    }
    if (paxosInstances != null
        ? !paxosInstances.equals(that.paxosInstances)
        : that.paxosInstances != null) {
      return false;
    }
    if (pendingValues != null
        ? !pendingValues.equals(that.pendingValues)
        : that.pendingValues != null) {
      return false;
    }

    return true;
  }
  @Override
  public void leave() {
    pendingValues.clear();
    bookedInstances.clear();
    commonState.setNextInstanceId(0);

    paxosInstances.leave();
  }
  /**
   * This patches the booked instances that are pending in case the configuration of the cluster
   * changes. This should be called only when we learn a ConfigurationChangeState i.e. when we
   * receive an accepted for such a message. This won't "learn" the message, as in applying it on
   * the cluster configuration, but will just update properly the set of acceptors for pending
   * instances.
   */
  @Override
  public void patchBookedInstances(ClusterMessage.ConfigurationChangeState value) {
    if (value.getJoin() != null) {
      for (InstanceId instanceId : bookedInstances.keySet()) {
        PaxosInstance instance = paxosInstances.getPaxosInstance(instanceId);
        if (instance.getAcceptors() != null) {
          instance
              .getAcceptors()
              .remove(commonState.configuration().getMembers().get(value.getJoin()));

          getLogger(ProposerContext.class)
              .debug(
                  "For booked instance "
                      + instance
                      + " removed gone member "
                      + commonState.configuration().getMembers().get(value.getJoin())
                      + " added joining member "
                      + value.getJoinUri());

          if (!instance.getAcceptors().contains(value.getJoinUri())) {
            instance.getAcceptors().add(value.getJoinUri());
          }
        }
      }
    } else if (value.getLeave() != null) {
      for (InstanceId instanceId : bookedInstances.keySet()) {
        PaxosInstance instance = paxosInstances.getPaxosInstance(instanceId);
        if (instance.getAcceptors() != null) {
          getLogger(ProposerContext.class)
              .debug(
                  "For booked instance "
                      + instance
                      + " removed leaving member "
                      + value.getLeave()
                      + " (at URI "
                      + commonState.configuration().getMembers().get(value.getLeave())
                      + ")");
          instance
              .getAcceptors()
              .remove(commonState.configuration().getMembers().get(value.getLeave()));
        }
      }
    }
  }
 @Override
 public PaxosInstance getPaxosInstance(InstanceId instanceId) {
   return paxosInstances.getPaxosInstance(instanceId);
 }