@Override
 public HighAvailabilityMemberState masterIsAvailable(
     HighAvailabilityMemberContext context, InstanceId masterId, URI masterHaURI) {
   if (masterId.equals(context.getMyId())) {
     throw new RuntimeException(
         "i ("
             + context.getMyId()
             + ") am trying to become a slave but "
             + "someone said i am available as master");
   }
   if (masterId.equals(context.getElectedMasterId())) {
     // A member joined and we all got the same event
     return this;
   }
   throw new RuntimeException(
       "my ("
           + context.getMyId()
           + ") current master is "
           + context.getAvailableHaMaster()
           + " (elected as "
           + context.getElectedMasterId()
           + " but i got a "
           + "masterIsAvailable event for "
           + masterHaURI);
 }
 @Override
 public HighAvailabilityMemberState masterIsElected(
     HighAvailabilityMemberContext context, InstanceId masterId) {
   if (masterId.equals(context.getMyId())) {
     return TO_MASTER;
   }
   if (masterId.equals(context.getElectedMasterId())) {
     return this;
   }
   return PENDING;
 }
 @Override
 public HighAvailabilityMemberState masterIsElected(
     HighAvailabilityMemberContext context, InstanceId masterId) {
   if (masterId.equals(context.getElectedMasterId())) {
     // A member joined and we all got the same event
     return this;
   }
   if (masterId.equals(context.getMyId())) {
     return TO_MASTER;
   }
   // This may mean the master changed from the time we transitioned here
   return PENDING;
 }
 @Override
 public HighAvailabilityMemberState masterIsAvailable(
     HighAvailabilityMemberContext context, InstanceId masterId, URI masterHaURI) {
   if (masterId.equals(context.getMyId())) {
     throw new RuntimeException("Cannot transition to MASTER directly from SLAVE state");
   } else if (masterId.equals(context.getElectedMasterId())) {
     // this is just someone else that joined the cluster
     return this;
   }
   throw new RuntimeException(
       "Received a MasterIsAvailable event for "
           + masterId
           + " which is different from the current master ("
           + context.getElectedMasterId()
           + ") while in the SLAVE state (probably missed a MasterIsElected event)");
 }
  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }

    MemberIsAvailable that = (MemberIsAvailable) o;

    if (!clusterUri.equals(that.clusterUri)) {
      return false;
    }
    if (!instanceId.equals(that.instanceId)) {
      return false;
    }
    if (!role.equals(that.role)) {
      return false;
    }
    if (!roleUri.equals(that.roleUri)) {
      return false;
    }

    return true;
  }
 @Override
 public HighAvailabilityMemberState slaveIsAvailable(
     HighAvailabilityMemberContext context, InstanceId slaveId, URI slaveUri) {
   if (slaveId.equals(context.getMyId())) {
     throw new RuntimeException("Cannot go from pending to slave");
   }
   return this;
 }
 @Override
 public HighAvailabilityMemberState slaveIsAvailable(
     HighAvailabilityMemberContext context, InstanceId slaveId, URI slaveUri) {
   if (slaveId.equals(context.getMyId())) {
     throw new RuntimeException("Cannot be master and transition to slave at the same time");
   }
   return this;
 }
 @Override
 public HighAvailabilityMemberState slaveIsAvailable(
     HighAvailabilityMemberContext context, InstanceId slaveId, URI slaveUri) {
   if (slaveId.equals(context.getMyId())) {
     return SLAVE;
   }
   return this;
 }
 @Override
 public HighAvailabilityMemberState masterIsElected(
     HighAvailabilityMemberContext context, InstanceId masterId) {
   assert context.getAvailableHaMaster() == null;
   if (masterId.equals(context.getMyId()) && !context.isSlaveOnly()) {
     return TO_MASTER;
   }
   return PENDING;
 }
 @Override
 public HighAvailabilityMemberState masterIsElected(
     HighAvailabilityMemberContext context, InstanceId masterId) {
   assert context.getAvailableHaMaster() == null;
   if (masterId.equals(context.getMyId())) {
     return this;
   }
   return PENDING; // everything still goes
 }
 @Override
 public HighAvailabilityMemberState masterIsAvailable(
     HighAvailabilityMemberContext context, InstanceId masterId, URI masterHaURI) {
   //                    assert context.getAvailableMaster() == null;
   if (masterId.equals(context.getMyId())) {
     throw new RuntimeException(
         "Received a MasterIsAvailable event for my InstanceId while in" + " PENDING state");
   }
   return TO_SLAVE;
 }
 @Override
 public HighAvailabilityMemberState masterIsElected(
     HighAvailabilityMemberContext context, InstanceId masterId) {
   if (masterId.equals(context.getMyId())) {
     return this;
   }
   // This means we (probably) were disconnected and got back in the cluster
   // and we find out that we are not the master anymore.
   return PENDING;
 }
 @Override
 public HighAvailabilityMemberState masterIsAvailable(
     HighAvailabilityMemberContext context, InstanceId masterId, URI masterHaURI) {
   if (masterId.equals(context.getMyId())) {
     return MASTER;
   }
   throw new RuntimeException(
       "Received a MasterIsAvailable event for instance "
           + masterId
           + " while in TO_MASTER state");
 }
 @Override
 public HighAvailabilityMemberState masterIsAvailable(
     HighAvailabilityMemberContext context, InstanceId masterId, URI masterHaURI) {
   if (masterId.equals(context.getMyId())) {
     return this;
   }
   throw new RuntimeException(
       "I, "
           + context.getMyId()
           + " got a masterIsAvailable for "
           + masterHaURI
           + " (id is "
           + masterId
           + " ) while in MASTER state. Probably missed a "
           + "MasterIsElected event.");
 }
Exemple #15
0
    @Override
    public HeartbeatState handle(
        HeartbeatContext context, Message<HeartbeatMessage> message, MessageHolder outgoing)
        throws Throwable {
      switch (message.getMessageType()) {
        case i_am_alive:
          {
            HeartbeatMessage.IAmAliveState state = message.getPayload();

            if (context.getClusterContext().isMe(state.getServer())) {
              break;
            }

            context.getClusterContext().getLogger(HeartbeatState.class).debug("Received " + state);

            if (state.getServer() == null) {
              break;
            }

            if (context.alive(state.getServer())) {
              // Send suspicions messages to all non-failed servers
              for (InstanceId aliveServer : context.getAlive()) {
                if (!aliveServer.equals(context.getClusterContext().getMyId())) {
                  URI aliveServerUri =
                      context.getClusterContext().configuration.getUriForId(aliveServer);
                  outgoing.offer(
                      Message.to(
                          HeartbeatMessage.suspicions,
                          aliveServerUri,
                          new HeartbeatMessage.SuspicionsState(
                              context.getSuspicionsFor(context.getClusterContext().getMyId()))));
                }
              }
            }

            context
                .getClusterContext()
                .timeouts
                .cancelTimeout(HeartbeatMessage.i_am_alive + "-" + state.getServer());
            context
                .getClusterContext()
                .timeouts
                .setTimeout(
                    HeartbeatMessage.i_am_alive + "-" + state.getServer(),
                    timeout(HeartbeatMessage.timed_out, message, state.getServer()));

            // Check if this server knows something that we don't
            if (message.hasHeader("last-learned")) {
              long lastLearned = Long.parseLong(message.getHeader("last-learned"));
              if (lastLearned
                  > context.getLearnerContext().getLastKnownLearnedInstanceInCluster()) {
                outgoing.offer(internal(LearnerMessage.catchUp, lastLearned));
              }
            }

            break;
          }

        case timed_out:
          {
            InstanceId server = message.getPayload();
            context
                .getClusterContext()
                .getLogger(HeartbeatState.class)
                .debug("Received timed out for server " + server);
            // Check if this node is no longer a part of the cluster
            if (context.getClusterContext().getConfiguration().getMembers().containsKey(server)) {
              context.suspect(server);

              context
                  .getClusterContext()
                  .timeouts
                  .setTimeout(
                      HeartbeatMessage.i_am_alive + "-" + server,
                      timeout(HeartbeatMessage.timed_out, message, server));

              // Send suspicions messages to all non-failed servers
              for (InstanceId aliveServer : context.getAlive()) {
                if (!aliveServer.equals(context.getClusterContext().getMyId())) {
                  URI sendTo =
                      context.getClusterContext().getConfiguration().getUriForId(aliveServer);
                  outgoing.offer(
                      Message.to(
                          HeartbeatMessage.suspicions,
                          sendTo,
                          new HeartbeatMessage.SuspicionsState(
                              context.getSuspicionsFor(context.getClusterContext().getMyId()))));
                }
              }
            } else {
              // If no longer part of cluster, then don't bother
              context.serverLeftCluster(server);
            }
            break;
          }

        case sendHeartbeat:
          {
            InstanceId to = message.getPayload();

            // Check if this node is no longer a part of the cluster
            if (!context.getClusterContext().isMe(to)
                && context.getClusterContext().getConfiguration().getMembers().containsKey(to)) {
              URI toSendTo = context.getClusterContext().getConfiguration().getUriForId(to);
              // Send heartbeat message to given server
              outgoing.offer(
                  to(
                          HeartbeatMessage.i_am_alive,
                          toSendTo,
                          new HeartbeatMessage.IAmAliveState(context.getClusterContext().getMyId()))
                      .setHeader(
                          "last-learned",
                          context.getLearnerContext().getLastLearnedInstanceId() + ""));

              // Set new timeout to send heartbeat to this host
              context
                  .getClusterContext()
                  .timeouts
                  .setTimeout(
                      HeartbeatMessage.sendHeartbeat + "-" + to,
                      timeout(HeartbeatMessage.sendHeartbeat, message, to));
            }
            break;
          }

        case reset_send_heartbeat:
          {
            InstanceId to = message.getPayload();

            if (!context.getClusterContext().isMe(to)) {
              String timeoutName = HeartbeatMessage.sendHeartbeat + "-" + to;
              context.getClusterContext().timeouts.cancelTimeout(timeoutName);
              context
                  .getClusterContext()
                  .timeouts
                  .setTimeout(timeoutName, timeout(HeartbeatMessage.sendHeartbeat, message, to));
            }
            break;
          }

        case suspicions:
          {
            HeartbeatMessage.SuspicionsState suspicions = message.getPayload();
            context
                .getClusterContext()
                .getLogger(HeartbeatState.class)
                .debug("Received suspicions as " + suspicions);

            URI from = new URI(message.getHeader(Message.FROM));
            InstanceId fromId = context.getClusterContext().getConfiguration().getServerId(from);
            /*
             * Remove ourselves from the suspicions received - we just received a message,
             * it's not normal to be considered failed. Whatever it was, it was transient and now it has
             * passed.
             */
            suspicions.getSuspicions().remove(context.getClusterContext().getMyId());
            context.suspicions(fromId, suspicions.getSuspicions());

            break;
          }

        case leave:
          {
            context.getClusterContext().getLogger(HeartbeatState.class).debug("Received leave");
            return start;
          }

        case addHeartbeatListener:
          {
            context.addHeartbeatListener((HeartbeatListener) message.getPayload());
            break;
          }

        case removeHeartbeatListener:
          {
            context.removeHeartbeatListener((HeartbeatListener) message.getPayload());
            break;
          }
      }

      return this;
    }