fusenapi/fsm/main.go

210 lines
5.1 KiB
Go
Raw Normal View History

2023-07-25 11:32:51 +00:00
package fsm
import (
"bytes"
"encoding/gob"
"fmt"
2023-07-26 02:52:33 +00:00
"fusenapi/utils/autoconfig"
2023-07-25 11:32:51 +00:00
"log"
"os"
2023-07-30 10:50:27 +00:00
"os/signal"
"path/filepath"
"runtime"
"syscall"
2023-07-25 11:32:51 +00:00
"time"
"github.com/hashicorp/raft"
2023-07-30 15:17:02 +00:00
"github.com/lni/dragonboat/v4"
"github.com/lni/dragonboat/v4/config"
"github.com/lni/dragonboat/v4/logger"
2023-07-25 11:32:51 +00:00
"gorm.io/gorm"
)
func test1() {
2023-07-30 15:17:02 +00:00
// log.SetFlags(log.Llongfile)
2023-07-25 11:32:51 +00:00
2023-07-30 15:17:02 +00:00
// fsm := StartNode("fs1", "localhost:5500", nil, initalize.InitMysql("fusentest:XErSYmLELKMnf3Dh@tcp(110.41.19.98:3306)/fusentest"))
2023-07-25 11:32:51 +00:00
2023-07-30 15:17:02 +00:00
// time.Sleep(time.Second * 5)
2023-07-25 11:32:51 +00:00
2023-07-30 15:17:02 +00:00
// for i := 0; i < 30; i++ {
// go log.Println(fsm.GetUserState(39))
// }
2023-07-25 11:32:51 +00:00
2023-07-30 15:17:02 +00:00
// log.Println(fsm.GetUserState(39))
2023-07-25 11:32:51 +00:00
2023-07-30 15:17:02 +00:00
// select {}
2023-07-25 11:32:51 +00:00
}
2023-07-30 10:50:27 +00:00
var addresses []string = []string{
"localhost:5500",
"localhost:5501",
"localhost:5502",
}
2023-07-30 16:41:04 +00:00
var shardID uint64 = 128
func StartNode(ServerID uint64, serverconfigs []*autoconfig.ConfigServer, gdb *gorm.DB) *SharedState {
2023-07-30 10:50:27 +00:00
// addr := "localhost"
// addr = fmt.Sprintf("%s:%d", addr, port)
// https://github.com/golang/go/issues/17393
if runtime.GOOS == "darwin" {
signal.Ignore(syscall.Signal(0xd))
}
initialMembers := make(map[uint64]string)
// when joining a new node which is not an initial members, the initialMembers
// map should be empty.
// when restarting a node that is not a member of the initial nodes, you can
// leave the initialMembers to be empty. we still populate the initialMembers
// here for simplicity.
2023-07-30 16:41:04 +00:00
for _, v := range serverconfigs {
2023-07-30 10:50:27 +00:00
// key is the ReplicaID, ReplicaID is not allowed to be 0
// value is the raft address
2023-07-30 16:41:04 +00:00
initialMembers[v.ReplicaId] = fmt.Sprintf("%s:%d", v.Host, v.Port-2000)
2023-07-30 10:50:27 +00:00
}
// for simplicity, in this example program, addresses of all those 3 initial
// raft members are hard coded. when address is not specified on the command
// line, we assume the node being launched is an initial raft member.
2023-07-30 16:41:04 +00:00
var nodeAddr = initialMembers[ServerID]
2023-07-30 10:50:27 +00:00
fmt.Fprintf(os.Stdout, "node address: %s\n", nodeAddr)
// change the log verbosity
logger.GetLogger("raft").SetLevel(logger.ERROR)
logger.GetLogger("rsm").SetLevel(logger.WARNING)
logger.GetLogger("transport").SetLevel(logger.WARNING)
logger.GetLogger("grpc").SetLevel(logger.WARNING)
// config for raft node
// See GoDoc for all available options
rc := config.Config{
// ShardID and ReplicaID of the raft node
2023-07-30 16:41:04 +00:00
ReplicaID: uint64(ServerID),
ShardID: shardID,
2023-07-30 10:50:27 +00:00
ElectionRTT: 10,
HeartbeatRTT: 1,
CheckQuorum: true,
SnapshotEntries: 10,
CompactionOverhead: 5,
}
datadir := filepath.Join(
2023-07-30 16:41:04 +00:00
"shared-state",
fmt.Sprintf("node%d", ServerID))
2023-07-30 10:50:27 +00:00
nhc := config.NodeHostConfig{
WALDir: datadir,
// NodeHostDir is where everything else is stored.
NodeHostDir: datadir,
// RTTMillisecond is the average round trip time between NodeHosts (usually
// on two machines/vms), it is in millisecond. Such RTT includes the
// processing delays caused by NodeHosts, not just the network delay between
// two NodeHost instances.
RTTMillisecond: 200,
// RaftAddress is used to identify the NodeHost instance
RaftAddress: nodeAddr,
}
nh, err := dragonboat.NewNodeHost(nhc)
if err != nil {
panic(err)
}
2023-07-30 16:41:04 +00:00
if err := nh.StartReplica(initialMembers, false, NewFsStateMachine, rc); err != nil {
2023-07-30 10:50:27 +00:00
fmt.Fprintf(os.Stderr, "failed to add cluster, %v\n", err)
os.Exit(1)
}
2023-07-30 16:41:04 +00:00
ss := &SharedState{
shardID: shardID,
replicaID: ServerID,
nh: nh,
2023-07-25 11:42:26 +00:00
}
2023-07-30 16:41:04 +00:00
return ss
2023-07-25 11:42:26 +00:00
}
2023-07-26 02:52:33 +00:00
// func JoinCluster(ServerID string, LeaderAddress string, RaftBind string, gdb *gorm.DB) *StateCluster {
// fsm := StartNode(ServerID, RaftBind, gdb)
// configFuture := fsm.ra.GetConfiguration()
// if err := configFuture.Error(); err != nil {
// log.Fatalf("failed to get raft configuration: %v", err)
// }
// for _, srv := range configFuture.Configuration().Servers {
// if srv.ID == raft.ServerID(ServerID) && srv.Address == raft.ServerAddress(LeaderAddress) {
// if future := fsm.ra.RemoveServer(srv.ID, 0, 0); future.Error() != nil {
// log.Fatalf("Error removing existing server [%s]: %v", ServerID, future.Error())
// }
// }
// }
// f := fsm.ra.AddVoter(raft.ServerID(ServerID), raft.ServerAddress(RaftBind), 0, 0)
// if f.Error() != nil {
// log.Fatalf("Error adding voter: %v", f.Error())
// }
// return fsm
// }
func waitForCluster(ra *raft.Raft) {
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
for range ticker.C {
state := ra.State()
if state == raft.Leader || state == raft.Follower {
log.Println("Raft cluster is running")
return
} else {
log.Println("Still waiting for the cluster to start...")
2023-07-25 11:32:51 +00:00
}
}
}
// var gdb *gorm.DB = initalize.InitMysql("fusentest:XErSYmLELKMnf3Dh@tcp(110.41.19.98:3306)/fusentest")
type UserState struct {
2023-07-30 10:50:27 +00:00
UpdateAt time.Time
UserId int64
PwdHash uint64
2023-07-25 11:32:51 +00:00
}
2023-07-30 10:50:27 +00:00
func (us *UserState) Encode(do func([]byte) error) error {
var buf bytes.Buffer
err := gob.NewEncoder(&buf).Encode(us)
2023-07-25 11:32:51 +00:00
if err != nil {
2023-07-30 10:50:27 +00:00
return err
}
if do != nil {
err := do(buf.Bytes())
if err != nil {
return err
}
2023-07-25 11:32:51 +00:00
}
2023-07-30 10:50:27 +00:00
return nil
}
func (us *UserState) Decode(data []byte) error {
buf := bytes.NewBuffer(data)
err := gob.NewDecoder(buf).Decode(us)
if err != nil {
return err
}
return nil
2023-07-25 11:32:51 +00:00
}