github.com/jpetazzo/etcd@v0.2.1-0.20140113055439-97f1363afac5/server/join_command.go (about)

     1  package server
     2  
     3  import (
     4  	"encoding/binary"
     5  
     6  	etcdErr "github.com/coreos/etcd/error"
     7  	"github.com/coreos/etcd/log"
     8  	"github.com/coreos/raft"
     9  )
    10  
    11  func init() {
    12  	raft.RegisterCommand(&JoinCommand{})
    13  }
    14  
    15  // The JoinCommand adds a node to the cluster.
    16  type JoinCommand struct {
    17  	MinVersion int    `json:"minVersion"`
    18  	MaxVersion int    `json:"maxVersion"`
    19  	Name       string `json:"name"`
    20  	RaftURL    string `json:"raftURL"`
    21  	EtcdURL    string `json:"etcdURL"`
    22  }
    23  
    24  func NewJoinCommand(minVersion int, maxVersion int, name, raftUrl, etcdUrl string) *JoinCommand {
    25  	return &JoinCommand{
    26  		MinVersion: minVersion,
    27  		MaxVersion: maxVersion,
    28  		Name:       name,
    29  		RaftURL:    raftUrl,
    30  		EtcdURL:    etcdUrl,
    31  	}
    32  }
    33  
    34  // The name of the join command in the log
    35  func (c *JoinCommand) CommandName() string {
    36  	return "etcd:join"
    37  }
    38  
    39  // Join a server to the cluster
    40  func (c *JoinCommand) Apply(context raft.Context) (interface{}, error) {
    41  	ps, _ := context.Server().Context().(*PeerServer)
    42  
    43  	b := make([]byte, 8)
    44  	binary.PutUvarint(b, context.CommitIndex())
    45  
    46  	// Make sure we're not getting a cached value from the registry.
    47  	ps.registry.Invalidate(c.Name)
    48  
    49  	// Check if the join command is from a previous peer, who lost all its previous log.
    50  	if _, ok := ps.registry.ClientURL(c.Name); ok {
    51  		return b, nil
    52  	}
    53  
    54  	// Check peer number in the cluster
    55  	if ps.registry.Count() == ps.MaxClusterSize {
    56  		log.Debug("Reject join request from ", c.Name)
    57  		return []byte{0}, etcdErr.NewError(etcdErr.EcodeNoMorePeer, "", context.CommitIndex())
    58  	}
    59  
    60  	// Add to shared peer registry.
    61  	ps.registry.Register(c.Name, c.RaftURL, c.EtcdURL)
    62  
    63  	// Add peer in raft
    64  	err := context.Server().AddPeer(c.Name, "")
    65  
    66  	// Add peer stats
    67  	if c.Name != ps.RaftServer().Name() {
    68  		ps.followersStats.Followers[c.Name] = &raftFollowerStats{}
    69  		ps.followersStats.Followers[c.Name].Latency.Minimum = 1 << 63
    70  	}
    71  
    72  	return b, err
    73  }
    74  
    75  func (c *JoinCommand) NodeName() string {
    76  	return c.Name
    77  }