func (r *raft) send(m pb.Message) {
	m.From = r.id
	if m.Type != pb.MsgProp {
		m.Term = r.Term
	}
	r.msgs = append(r.msgs, m)
}
send persists state to stable storage and then sends to its mailbox.
package raft
import (
	"errors"
	"fmt"
	"math"
	"math/rand"
	"sort"
	"strings"
	pb "github.com/coreos/etcd/raft/raftpb"
)
const None uint64 = 0
const noLimit = math.MaxUint64
var errNoLeader = errors.New("no leader")
const (
	StateFollower StateType = iota
	StateCandidate
	StateLeader
)
type StateType uint64
var stmap = [...]string{
	"StateFollower",
	"StateCandidate",
	"StateLeader",
}
func (st StateType) String() string {
	return stmap[uint64(st)]
}
type Config struct {
	ID uint64
	peers []uint64
	ElectionTick int
	HeartbeatTick int
	Storage Storage
	Applied uint64
	MaxSizePerMsg uint64
	MaxInflightMsgs int
	Logger Logger
}
func (c *Config) validate() error {
	if c.ID == None {
		return errors.New("cannot use none as id")
	}
	if c.HeartbeatTick <= 0 {
		return errors.New("heartbeat tick must be greater than 0")
	}
	if c.ElectionTick <= c.HeartbeatTick {
		return errors.New("election tick must be greater than heartbeat tick")
	}
	if c.Storage == nil {
		return errors.New("storage cannot be nil")
	}
	if c.MaxInflightMsgs <= 0 {
		return errors.New("max inflight messages must be greater than 0")
	}
	if c.Logger == nil {
		c.Logger = raftLogger
	}
	return nil
}
type raft struct {
	pb.HardState
	id uint64
	raftLog *raftLog
	maxInflight int
	maxMsgSize  uint64
	prs         map[uint64]*Progress
	state StateType
	votes map[uint64]bool
	msgs []pb.Message
	lead uint64
	pendingConf bool
	elapsed          int  
	heartbeatTimeout int
	electionTimeout  int
	rand             *rand.Rand
	tick             func()
	step             stepFunc
	logger Logger
}
func newRaft(c *Config) *raft {
	if err := c.validate(); err != nil {
		panic(err.Error())
	}
	raftlog := newLog(c.Storage, c.Logger)
	hs, cs, err := c.Storage.InitialState()
	if err != nil {
		panic(err)  
	}
	peers := c.peers
	if len(cs.Nodes) > 0 {
		if len(peers) > 0 {
			panic("cannot specify both newRaft(peers) and ConfState.Nodes)")
		}
		peers = cs.Nodes
	}
	r := &raft{
		id:      c.ID,
		lead:    None,
		raftLog: raftlog,
		maxMsgSize:       c.MaxSizePerMsg,
		maxInflight:      c.MaxInflightMsgs,
		prs:              make(map[uint64]*Progress),
		electionTimeout:  c.ElectionTick,
		heartbeatTimeout: c.HeartbeatTick,
		logger:           c.Logger,
	}
	r.rand = rand.New(rand.NewSource(int64(c.ID)))
	for _, p := range peers {
		r.prs[p] = &Progress{Next: 1, ins: newInflights(r.maxInflight)}
	}
	if !isHardStateEqual(hs, emptyState) {
		r.loadState(hs)
	}
	if c.Applied > 0 {
		raftlog.appliedTo(c.Applied)
	}
	r.becomeFollower(r.Term, None)
	nodesStrs := make([]string, 0)
	for _, n := range r.nodes() {
		nodesStrs = append(nodesStrs, fmt.Sprintf("%x", n))
	}
	r.logger.Infof("newRaft %x [peers: [%s], term: %d, commit: %d, applied: %d, lastindex: %d, lastterm: %d]",
		r.id, strings.Join(nodesStrs, ","), r.Term, r.raftLog.committed, r.raftLog.applied, r.raftLog.lastIndex(), r.raftLog.lastTerm())
	return r
}
func (r *raft) hasLeader() bool { return r.lead != None }
func (r *raft) softState() *SoftState { return &SoftState{Lead: r.lead, RaftState: r.state} }
func (r *raft) q() int { return len(r.prs)/2 + 1 }
func (r *raft) nodes() []uint64 {
	nodes := make([]uint64, 0, len(r.prs))
	for k := range r.prs {
		nodes = append(nodes, k)
	}
	sort.Sort(uint64Slice(nodes))
	return nodes
}