protected void performBasicCheck() {
    // update all alive times
    Member[] members = super.getMembers();
    for (int i = 0; members != null && i < members.length; i++) {
      if (addSuspects.containsKey(members[i]) && membership.getMember(members[i]) == null) {
        // avoid temporary adding member.
        continue;
      }
      if (membership.memberAlive((MemberImpl) members[i])) {
        // we don't have this one in our membership, check to see if he/she is alive
        if (memberAlive(members[i])) {
          log.warn("Member added, even though we werent notified:" + members[i]);
          super.memberAdded(members[i]);
        } else {
          membership.removeMember((MemberImpl) members[i]);
        }
      }
    }

    // check suspect members if they are still alive,
    // if not, simply issue the memberDisappeared message
    MemberImpl[] keys = removeSuspects.keySet().toArray(new MemberImpl[removeSuspects.size()]);
    for (int i = 0; i < keys.length; i++) {
      MemberImpl m = keys[i];
      if (membership.getMember(m) != null && (!memberAlive(m))) {
        membership.removeMember(m);
        super.memberDisappeared(m);
        removeSuspects.remove(m);
        if (log.isInfoEnabled()) log.info("Suspect member, confirmed dead.[" + m + "]");
      } else {
        if (removeSuspectsTimeout > 0) {
          long timeNow = System.currentTimeMillis();
          int timeIdle = (int) ((timeNow - removeSuspects.get(m).longValue()) / 1000L);
          if (timeIdle > removeSuspectsTimeout) {
            removeSuspects.remove(m); // remove suspect member
          }
        }
      }
    }

    // check add suspects members if they are alive now,
    // if they are, simply issue the memberAdded message
    keys = addSuspects.keySet().toArray(new MemberImpl[addSuspects.size()]);
    for (int i = 0; i < keys.length; i++) {
      MemberImpl m = keys[i];
      if (membership.getMember(m) == null && (memberAlive(m))) {
        membership.memberAlive(m);
        super.memberAdded(m);
        addSuspects.remove(m);
        if (log.isInfoEnabled()) log.info("Suspect member, confirmed alive.[" + m + "]");
      }
    }
  }
  /**
   * Runs a refresh cycle and returns a list of members that has expired. This also removes the
   * members from the membership, in such a way that getMembers() = getMembers() - expire()
   *
   * @param maxtime - the max time a member can remain unannounced before it is considered dead.
   * @return the list of expired members
   */
  public synchronized org.apache.catalina.tribes.membership.MemberImplRemoteInterface[] expire(
      long maxtime) throws RemoteException {
    try {
      if (!hasMembers()) return EMPTY_MEMBERS;

      ArrayList<org.apache.catalina.tribes.membership.MemberImplRemoteInterface> list = null;
      Iterator<org.apache.catalina.tribes.membership.MembershipMbrEntryRemoteInterface> i =
          getMapData().values().iterator();
      while (i.hasNext()) {
        org.apache.catalina.tribes.membership.MembershipMbrEntryRemoteInterface entry = i.next();
        if (entry.hasExpired(maxtime)) {
          if (list == null) // only need a list when members are expired (smaller gc)
          list =
                new java.util.ArrayList<
                    org.apache.catalina.tribes.membership.MemberImplRemoteInterface>();
          list.add(entry.getMember());
        }
      }

      if (list != null) {
        org.apache.catalina.tribes.membership.MemberImplRemoteInterface[] result =
            new org.apache.catalina.tribes.membership.MemberImplRemoteInterface[list.size()];
        list.toArray(result);
        for (int j = 0; j < result.length; j++) {
          removeMember(result[j]);
        }
        return result;
      } else {
        return EMPTY_MEMBERS;
      }
    } catch (Exception excp) {
      excp.printStackTrace();
    }
    return null;
  }
 protected void performForcedCheck() {
   // update all alive times
   Member[] members = super.getMembers();
   for (int i = 0; members != null && i < members.length; i++) {
     if (memberAlive(members[i])) {
       if (membership.memberAlive((MemberImpl) members[i])) super.memberAdded(members[i]);
       addSuspects.remove(members[i]);
     } else {
       if (membership.getMember(members[i]) != null) {
         membership.removeMember((MemberImpl) members[i]);
         removeSuspects.remove(members[i]);
         if (members[i] instanceof StaticMember) {
           addSuspects.put(members[i], Long.valueOf(System.currentTimeMillis()));
         }
         super.memberDisappeared(members[i]);
       }
     }
   }
 }
 @Override
 public void memberDisappeared(Member member) {
   if (membership == null) setupMembership();
   boolean notify = false;
   boolean shutdown = Arrays.equals(member.getCommand(), Member.SHUTDOWN_PAYLOAD);
   if (!shutdown)
     if (log.isInfoEnabled())
       log.info("Received memberDisappeared[" + member + "] message. Will verify.");
   synchronized (membership) {
     if (!membership.contains(member)) {
       if (log.isInfoEnabled())
         log.info("Verification complete. Member already disappeared[" + member + "]");
       return;
     }
     // check to see if the member really is gone
     // if the payload is not a shutdown message
     if (shutdown || !memberAlive(member)) {
       // not correct, we need to maintain the map
       membership.removeMember((MemberImpl) member);
       removeSuspects.remove(member);
       if (member instanceof StaticMember) {
         addSuspects.put(member, Long.valueOf(System.currentTimeMillis()));
       }
       notify = true;
     } else {
       // add the member as suspect
       removeSuspects.put(member, Long.valueOf(System.currentTimeMillis()));
     }
   }
   if (notify) {
     if (log.isInfoEnabled())
       log.info("Verification complete. Member disappeared[" + member + "]");
     super.memberDisappeared(member);
   } else {
     if (log.isInfoEnabled())
       log.info("Verification complete. Member still alive[" + member + "]");
   }
 }