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.

162 lines
3.8 KiB

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