...

Source file src/go.etcd.io/etcd/raft/v3/rafttest/interaction_env_handler_stabilize.go

Documentation: go.etcd.io/etcd/raft/v3/rafttest

     1  // Copyright 2019 The etcd Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package rafttest
    16  
    17  import (
    18  	"fmt"
    19  	"testing"
    20  
    21  	"github.com/cockroachdb/datadriven"
    22  	"go.etcd.io/etcd/raft/v3/raftpb"
    23  )
    24  
    25  func (env *InteractionEnv) handleStabilize(t *testing.T, d datadriven.TestData) error {
    26  	idxs := nodeIdxs(t, d)
    27  	return env.Stabilize(idxs...)
    28  }
    29  
    30  // Stabilize repeatedly runs Ready handling on and message delivery to the set
    31  // of nodes specified via the idxs slice until reaching a fixed point.
    32  func (env *InteractionEnv) Stabilize(idxs ...int) error {
    33  	var nodes []Node
    34  	for _, idx := range idxs {
    35  		nodes = append(nodes, env.Nodes[idx])
    36  	}
    37  	if len(nodes) == 0 {
    38  		nodes = env.Nodes
    39  	}
    40  
    41  	for {
    42  		done := true
    43  		for _, rn := range nodes {
    44  			if rn.HasReady() {
    45  				done = false
    46  				idx := int(rn.Status().ID - 1)
    47  				fmt.Fprintf(env.Output, "> %d handling Ready\n", idx+1)
    48  				env.withIndent(func() { env.ProcessReady(idx) })
    49  			}
    50  		}
    51  		for _, rn := range nodes {
    52  			id := rn.Status().ID
    53  			// NB: we grab the messages just to see whether to print the header.
    54  			// DeliverMsgs will do it again.
    55  			if msgs, _ := splitMsgs(env.Messages, id); len(msgs) > 0 {
    56  				fmt.Fprintf(env.Output, "> %d receiving messages\n", id)
    57  				env.withIndent(func() { env.DeliverMsgs(Recipient{ID: id}) })
    58  				done = false
    59  			}
    60  		}
    61  		if done {
    62  			return nil
    63  		}
    64  	}
    65  }
    66  
    67  func splitMsgs(msgs []raftpb.Message, to uint64) (toMsgs []raftpb.Message, rmdr []raftpb.Message) {
    68  	// NB: this method does not reorder messages.
    69  	for _, msg := range msgs {
    70  		if msg.To == to {
    71  			toMsgs = append(toMsgs, msg)
    72  		} else {
    73  			rmdr = append(rmdr, msg)
    74  		}
    75  	}
    76  	return toMsgs, rmdr
    77  }
    78  

View as plain text