join_command.go 1.8 KB

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