ClusterState configure(Configuration configuration) {
    Assert.notNull(configuration, "configuration");

    // If the configuration index is less than the currently configured index, ignore it.
    // Configurations can be persisted and applying old configurations can revert newer configurations.
    if (this.configuration != null && configuration.index() <= this.configuration.index())
      return this;

    Instant time = Instant.ofEpochMilli(configuration.time());

    // Iterate through members in the new configuration, add any missing members, and update existing members.
    boolean transition = false;
    for (Member member : configuration.members()) {
      if (member.equals(this.member)) {
        transition = this.member.type().ordinal() < member.type().ordinal();
        this.member.update(member.type(), time).update(member.clientAddress(), time);
        members.add(this.member);
      } else {
        // If the member state doesn't already exist, create it.
        MemberState state = membersMap.get(member.id());
        if (state == null) {
          state = new MemberState(new ServerMember(member.type(), member.serverAddress(), member.clientAddress(), time), this);
          state.resetState(context.getLog());
          this.members.add(state.getMember());
          this.remoteMembers.add(state);
          membersMap.put(member.id(), state);
          addressMap.put(member.address(), state);
          joinListeners.accept(state.getMember());
        }

        // If the member type has changed, update the member type and reset its state.
        state.getMember().update(member.clientAddress(), time);
        if (state.getMember().type() != member.type()) {
          state.getMember().update(member.type(), time);
          state.resetState(context.getLog());
        }

        // If the member status has changed, update the local member status.
        if (state.getMember().status() != member.status()) {
          state.getMember().update(member.status(), time);
        }

        // Update the optimized member collections according to the member type.
        for (List<MemberState> memberType : memberTypes.values()) {
          memberType.remove(state);
        }

        List<MemberState> memberType = memberTypes.get(member.type());
        if (memberType == null) {
          memberType = new CopyOnWriteArrayList<>();
          memberTypes.put(member.type(), memberType);
        }
        memberType.add(state);
      }
    }

    // Transition the local member only if the member is being promoted and not demoted.
    // Configuration changes that demote the local member are only applied to the local server
    // upon commitment. This ensures that e.g. a leader that's removing itself from the quorum
    // can commit the configuration change prior to shutting down.
    if (transition) {
      context.transition(this.member.type());
    }

    // Iterate through configured members and remove any that no longer exist in the configuration.
    int i = 0;
    while (i < this.remoteMembers.size()) {
      MemberState member = this.remoteMembers.get(i);
      if (!configuration.members().contains(member.getMember())) {
        this.members.remove(member.getMember());
        this.remoteMembers.remove(i);
        for (List<MemberState> memberType : memberTypes.values()) {
          memberType.remove(member);
        }
        membersMap.remove(member.getMember().id());
        addressMap.remove(member.getMember().address());
        leaveListeners.accept(member.getMember());
      } else {
        i++;
      }
    }

    // If the local member was removed from the cluster, remove it from the members list.
    if (!configuration.members().contains(member)) {
      members.remove(member);
    }

    this.configuration = configuration;

    // Store the configuration if it's already committed.
    if (context.getCommitIndex() >= configuration.index()) {
      context.getMetaStore().storeConfiguration(configuration);
    }

    // Reassign members based on availability.
    reassign();

    return this;
  }
ClusterState configure ( Configuration configuration ) { Assert . notNull ( configuration , "configuration" ) ; if ( this . configuration != null && configuration . index ( ) <= this . configuration . index ( ) ) return this ; Instant time = Instant . ofEpochMilli ( configuration . time ( ) ) ; boolean transition = false ; for ( Member member : configuration . members ( ) ) { if ( member . equals ( this . member ) ) { transition = this . member . type ( ) . ordinal ( ) < member . type ( ) . ordinal ( ) ; this . member . update ( member . type ( ) , time ) . update ( member . clientAddress ( ) , time ) ; members . add ( this . member ) ; } else { MemberState state = membersMap . get ( member . id ( ) ) ; if ( state == null ) { state = new MemberState ( new ServerMember ( member . type ( ) , member . serverAddress ( ) , member . clientAddress ( ) , time ) , this ) ; state . resetState ( context . getLog ( ) ) ; this . members . add ( state . getMember ( ) ) ; this . remoteMembers . add ( state ) ; membersMap . put ( member . id ( ) , state ) ; addressMap . put ( member . address ( ) , state ) ; joinListeners . accept ( state . getMember ( ) ) ; } state . getMember ( ) . update ( member . clientAddress ( ) , time ) ; if ( state . getMember ( ) . type ( ) != member . type ( ) ) { state . getMember ( ) . update ( member . type ( ) , time ) ; state . resetState ( context . getLog ( ) ) ; } if ( state . getMember ( ) . status ( ) != member . status ( ) ) { state . getMember ( ) . update ( member . status ( ) , time ) ; } for ( List < MemberState > memberType : memberTypes . values ( ) ) { memberType . remove ( state ) ; } List < MemberState > memberType = memberTypes . get ( member . type ( ) ) ; if ( memberType == null ) { memberType = new CopyOnWriteArrayList < > ( ) ; memberTypes . put ( member . type ( ) , memberType ) ; } memberType . add ( state ) ; } } if ( transition ) { context . transition ( this . member . type ( ) ) ; } int i = 0 ; while ( i < this . remoteMembers . size ( ) ) { MemberState member = this . remoteMembers . get ( i ) ; if ( ! configuration . members ( ) . contains ( member . getMember ( ) ) ) { this . members . remove ( member . getMember ( ) ) ; this . remoteMembers . remove ( i ) ; for ( List < MemberState > memberType : memberTypes . values ( ) ) { memberType . remove ( member ) ; } membersMap . remove ( member . getMember ( ) . id ( ) ) ; addressMap . remove ( member . getMember ( ) . address ( ) ) ; leaveListeners . accept ( member . getMember ( ) ) ; } else { i ++ ; } } if ( ! configuration . members ( ) . contains ( member ) ) { members . remove ( member ) ; } this . configuration = configuration ; if ( context . getCommitIndex ( ) >= configuration . index ( ) ) { context . getMetaStore ( ) . storeConfiguration ( configuration ) ; } reassign ( ) ; return this ; }
Configures the cluster state.

@param configuration The cluster configuration.
@return The cluster state.