李度、马也驰 25spring数据库系统 p1仓库
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.
 

105 lines
2.0 KiB

package nodes
import (
"io"
"net"
"net/http"
"net/rpc"
"os"
"simple-kv-store/internal/logprovider"
"time"
"go.uber.org/zap"
)
var log, _ = logprovider.CreateDefaultZapLogger(zap.InfoLevel)
func newNode(address string) *Public_node_info {
return &Public_node_info{
connect: false,
address: address,
}
}
func Init(id int, nodeAddr []string, pipe string) *Node {
ns := make(map[int]*Public_node_info)
for k, v := range nodeAddr {
ns[k] = newNode(v)
}
// 创建节点
return &Node{
self: id,
nodes: ns,
pipeAddr: pipe,
}
}
func Start(node *Node, isLeader bool) {
if isLeader {
node.state = Candidate // 需要身份转变
} else {
node.state = Follower
}
go func() {
for {
switch node.state {
case Follower:
case Candidate:
// candidate发布一个监听输入线程后,变成leader
node.state = Leader
go func() {
if node.pipeAddr == "" {
log.Error("暂不支持非管道读入")
}
pipe, err := os.Open(node.pipeAddr)
if err != nil {
log.Error("Failed to open pipe")
}
defer pipe.Close()
// 不断读取管道中的输入
buffer := make([]byte, 256)
for {
n, err := pipe.Read(buffer)
if err != nil && err != io.EOF {
log.Error("Error reading from pipe")
}
if n > 0 {
input := string(buffer[:n])
log.Info("send : " + input)
// 将用户输入封装成一个 LogEntry
kv := LogEntry{input, ""}
node.log = append(node.log, kv)
// 广播给其它节点
node.BroadCastKV(kv)
}
}
}()
case Leader:
time.Sleep(50 * time.Millisecond)
}
}
}()
}
func (node *Node) Rpc(port string) {
err := rpc.Register(node)
if err != nil {
log.Fatal("rpc register failed", zap.Error(err))
}
rpc.HandleHTTP()
l, e := net.Listen("tcp", port)
if e != nil {
log.Fatal("listen error:", zap.Error(err))
}
go func() {
err := http.Serve(l, nil)
if err != nil {
log.Fatal("http server error:", zap.Error(err))
}
}()
}