You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
3.7 KiB

5 years ago
5 years ago
11 years ago
6 years ago
  1. package weed_server
  2. import (
  3. "encoding/json"
  4. "math/rand"
  5. "os"
  6. "path"
  7. "sort"
  8. "time"
  9. "google.golang.org/grpc"
  10. "github.com/chrislusf/seaweedfs/weed/pb"
  11. "github.com/chrislusf/raft"
  12. "github.com/chrislusf/seaweedfs/weed/glog"
  13. "github.com/chrislusf/seaweedfs/weed/topology"
  14. )
  15. type RaftServer struct {
  16. peers []string // initial peers to join with
  17. raftServer raft.Server
  18. dataDir string
  19. serverAddr string
  20. topo *topology.Topology
  21. *raft.GrpcServer
  22. }
  23. type StateMachine struct {
  24. raft.StateMachine
  25. topo *topology.Topology
  26. }
  27. func (s StateMachine) Save() ([]byte, error) {
  28. state := topology.MaxVolumeIdCommand{
  29. MaxVolumeId: s.topo.GetMaxVolumeId(),
  30. }
  31. glog.V(1).Infof("Save raft state %+v", state)
  32. return json.Marshal(state)
  33. }
  34. func (s StateMachine) Recovery(data []byte) error {
  35. state := topology.MaxVolumeIdCommand{}
  36. err := json.Unmarshal(data, &state)
  37. if err != nil {
  38. return err
  39. }
  40. glog.V(1).Infof("Recovery raft state %+v", state)
  41. s.topo.UpAdjustMaxVolumeId(state.MaxVolumeId)
  42. return nil
  43. }
  44. func NewRaftServer(grpcDialOption grpc.DialOption, peers []string, serverAddr, dataDir string, topo *topology.Topology, raftResumeState bool) (*RaftServer, error) {
  45. s := &RaftServer{
  46. peers: peers,
  47. serverAddr: serverAddr,
  48. dataDir: dataDir,
  49. topo: topo,
  50. }
  51. if glog.V(4) {
  52. raft.SetLogLevel(2)
  53. }
  54. raft.RegisterCommand(&topology.MaxVolumeIdCommand{})
  55. var err error
  56. transporter := raft.NewGrpcTransporter(grpcDialOption)
  57. glog.V(0).Infof("Starting RaftServer with %v", serverAddr)
  58. if !raftResumeState {
  59. // always clear previous metadata
  60. os.RemoveAll(path.Join(s.dataDir, "conf"))
  61. os.RemoveAll(path.Join(s.dataDir, "log"))
  62. os.RemoveAll(path.Join(s.dataDir, "snapshot"))
  63. }
  64. if err := os.MkdirAll(path.Join(s.dataDir, "snapshot"), 0600); err != nil {
  65. return nil, err
  66. }
  67. stateMachine := StateMachine{topo: topo}
  68. s.raftServer, err = raft.NewServer(s.serverAddr, s.dataDir, transporter, stateMachine, topo, "")
  69. if err != nil {
  70. glog.V(0).Infoln(err)
  71. return nil, err
  72. }
  73. s.raftServer.SetHeartbeatInterval(time.Duration(300+rand.Intn(150)) * time.Millisecond)
  74. s.raftServer.SetElectionTimeout(10 * time.Second)
  75. if err := s.raftServer.LoadSnapshot(); err != nil {
  76. return nil, err
  77. }
  78. if err := s.raftServer.Start(); err != nil {
  79. return nil, err
  80. }
  81. for _, peer := range s.peers {
  82. if err := s.raftServer.AddPeer(peer, pb.ServerToGrpcAddress(peer)); err != nil {
  83. return nil, err
  84. }
  85. }
  86. // Remove deleted peers
  87. for existsPeerName := range s.raftServer.Peers() {
  88. exists, existingPeer := false, ""
  89. for _, peer := range s.peers {
  90. if pb.ServerToGrpcAddress(peer) == existsPeerName {
  91. exists, existingPeer = true, peer
  92. break
  93. }
  94. }
  95. if exists {
  96. if err := s.raftServer.RemovePeer(existsPeerName); err != nil {
  97. glog.V(0).Infoln(err)
  98. return nil, err
  99. } else {
  100. glog.V(0).Infof("removing old peer %s", existingPeer)
  101. }
  102. }
  103. }
  104. s.GrpcServer = raft.NewGrpcServer(s.raftServer)
  105. if s.raftServer.IsLogEmpty() && isTheFirstOne(serverAddr, s.peers) {
  106. // Initialize the server by joining itself.
  107. // s.DoJoinCommand()
  108. }
  109. glog.V(0).Infof("current cluster leader: %v", s.raftServer.Leader())
  110. return s, nil
  111. }
  112. func (s *RaftServer) Peers() (members []string) {
  113. peers := s.raftServer.Peers()
  114. for _, p := range peers {
  115. members = append(members, p.Name)
  116. }
  117. return
  118. }
  119. func isTheFirstOne(self string, peers []string) bool {
  120. sort.Strings(peers)
  121. if len(peers) <= 0 {
  122. return true
  123. }
  124. return self == peers[0]
  125. }
  126. func (s *RaftServer) DoJoinCommand() {
  127. glog.V(0).Infoln("Initializing new cluster")
  128. if _, err := s.raftServer.Do(&raft.DefaultJoinCommand{
  129. Name: s.raftServer.Name(),
  130. ConnectionString: pb.ServerToGrpcAddress(s.serverAddr),
  131. }); err != nil {
  132. glog.Errorf("fail to send join command: %v", err)
  133. }
  134. }