cluster.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package etcdserver
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "net/url"
  6. "sort"
  7. "strings"
  8. "github.com/coreos/etcd/pkg/flags"
  9. "github.com/coreos/etcd/pkg/types"
  10. )
  11. // Cluster is a list of Members that belong to the same raft cluster
  12. type Cluster map[int64]*Member
  13. func (c Cluster) FindID(id int64) *Member {
  14. return c[id]
  15. }
  16. func (c Cluster) FindName(name string) *Member {
  17. for _, m := range c {
  18. if m.Name == name {
  19. return m
  20. }
  21. }
  22. return nil
  23. }
  24. func (c Cluster) Add(m Member) error {
  25. if c.FindID(m.ID) != nil {
  26. return fmt.Errorf("Member exists with identical ID %v", m)
  27. }
  28. c[m.ID] = &m
  29. return nil
  30. }
  31. func (c *Cluster) AddSlice(mems []Member) error {
  32. for _, m := range mems {
  33. err := c.Add(m)
  34. if err != nil {
  35. return err
  36. }
  37. }
  38. return nil
  39. }
  40. // Pick chooses a random address from a given Member's addresses, and returns it as
  41. // an addressible URI. If the given member does not exist, an empty string is returned.
  42. func (c Cluster) Pick(id int64) string {
  43. if m := c.FindID(id); m != nil {
  44. urls := m.PeerURLs
  45. if len(urls) == 0 {
  46. return ""
  47. }
  48. return urls[rand.Intn(len(urls))]
  49. }
  50. return ""
  51. }
  52. // Set parses command line sets of names to IPs formatted like:
  53. // mach0=http://1.1.1.1,mach0=http://2.2.2.2,mach0=http://1.1.1.1,mach1=http://2.2.2.2,mach1=http://3.3.3.3
  54. func (c *Cluster) Set(s string) error {
  55. *c = Cluster{}
  56. v, err := url.ParseQuery(strings.Replace(s, ",", "&", -1))
  57. if err != nil {
  58. return err
  59. }
  60. for name, urls := range v {
  61. if len(urls) == 0 || urls[0] == "" {
  62. return fmt.Errorf("Empty URL given for %q", name)
  63. }
  64. m := newMember(name, types.URLs(*flags.NewURLsValue(strings.Join(urls, ","))), nil)
  65. err := c.Add(*m)
  66. if err != nil {
  67. return err
  68. }
  69. }
  70. return nil
  71. }
  72. func (c Cluster) String() string {
  73. sl := []string{}
  74. for _, m := range c {
  75. for _, u := range m.PeerURLs {
  76. sl = append(sl, fmt.Sprintf("%s=%s", m.Name, u))
  77. }
  78. }
  79. sort.Strings(sl)
  80. return strings.Join(sl, ",")
  81. }
  82. func (c Cluster) IDs() []int64 {
  83. var ids []int64
  84. for _, m := range c {
  85. ids = append(ids, m.ID)
  86. }
  87. sort.Sort(types.Int64Slice(ids))
  88. return ids
  89. }
  90. // PeerURLs returns a list of all peer addresses. Each address is prefixed
  91. // with the scheme (currently "http://"). The returned list is sorted in
  92. // ascending lexicographical order.
  93. func (c Cluster) PeerURLs() []string {
  94. endpoints := make([]string, 0)
  95. for _, p := range c {
  96. for _, addr := range p.PeerURLs {
  97. endpoints = append(endpoints, addr)
  98. }
  99. }
  100. sort.Strings(endpoints)
  101. return endpoints
  102. }
  103. // ClientURLs returns a list of all client addresses. Each address is prefixed
  104. // with the scheme (currently "http://"). The returned list is sorted in
  105. // ascending lexicographical order.
  106. func (c Cluster) ClientURLs() []string {
  107. urls := make([]string, 0)
  108. for _, p := range c {
  109. for _, url := range p.ClientURLs {
  110. urls = append(urls, url)
  111. }
  112. }
  113. sort.Strings(urls)
  114. return urls
  115. }