|
@ -1,8 +1,10 @@ |
|
|
package nodes |
|
|
package nodes |
|
|
|
|
|
|
|
|
import ( |
|
|
import ( |
|
|
|
|
|
"math/rand" |
|
|
"net/rpc" |
|
|
"net/rpc" |
|
|
"strconv" |
|
|
"strconv" |
|
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
"github.com/syndtr/goleveldb/leveldb" |
|
|
"github.com/syndtr/goleveldb/leveldb" |
|
|
"go.uber.org/zap" |
|
|
"go.uber.org/zap" |
|
@ -38,22 +40,33 @@ type Node struct { |
|
|
log map[int]LogEntry |
|
|
log map[int]LogEntry |
|
|
|
|
|
|
|
|
// leader用来标记新log
|
|
|
// leader用来标记新log
|
|
|
maxLogId int |
|
|
|
|
|
|
|
|
maxLogId int |
|
|
|
|
|
|
|
|
db *leveldb.DB |
|
|
db *leveldb.DB |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (node *Node) BroadCastKV(logId int, kv LogEntry) { |
|
|
|
|
|
|
|
|
func (node *Node) BroadCastKV(logId int, kvCall LogEntryCall) { |
|
|
// 遍历所有节点
|
|
|
// 遍历所有节点
|
|
|
for id, _ := range node.nodes { |
|
|
for id, _ := range node.nodes { |
|
|
go func(id string, kv LogEntry) { |
|
|
|
|
|
|
|
|
go func(id string, kv LogEntryCall) { |
|
|
var reply KVReply |
|
|
var reply KVReply |
|
|
node.sendKV(id, logId, kv, &reply) |
|
|
|
|
|
}(id, kv) |
|
|
|
|
|
|
|
|
node.sendKV(id, logId, kvCall, &reply) |
|
|
|
|
|
}(id, kvCall) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (node *Node) sendKV(id string, logId int, kv LogEntry, reply *KVReply) { |
|
|
|
|
|
|
|
|
func (node *Node) sendKV(id string, logId int, kvCall LogEntryCall, reply *KVReply) { |
|
|
|
|
|
switch kvCall.CallState { |
|
|
|
|
|
case Fail: |
|
|
|
|
|
log.Info("模拟发送失败") |
|
|
|
|
|
// 这么写向所有的node发送都失败,也可以随机数确定是否失败
|
|
|
|
|
|
case Delay: |
|
|
|
|
|
log.Info("模拟发送延迟") |
|
|
|
|
|
// 随机延迟0-5ms
|
|
|
|
|
|
time.Sleep(time.Millisecond * time.Duration(rand.Intn(5))) |
|
|
|
|
|
default: |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
client, err := rpc.DialHTTP("tcp", node.nodes[id].address) |
|
|
client, err := rpc.DialHTTP("tcp", node.nodes[id].address) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
log.Error("dialing: ", zap.Error(err)) |
|
|
log.Error("dialing: ", zap.Error(err)) |
|
@ -67,16 +80,16 @@ func (node *Node) sendKV(id string, logId int, kv LogEntry, reply *KVReply) { |
|
|
} |
|
|
} |
|
|
}(client) |
|
|
}(client) |
|
|
|
|
|
|
|
|
arg := LogIdAndEntry{logId, kv} |
|
|
|
|
|
|
|
|
arg := LogIdAndEntry{logId, kvCall.LogE} |
|
|
callErr := client.Call("Node.ReceiveKV", arg, reply) // RPC
|
|
|
callErr := client.Call("Node.ReceiveKV", arg, reply) // RPC
|
|
|
if callErr != nil { |
|
|
if callErr != nil { |
|
|
log.Error("dialing node_" + id + "fail: ", zap.Error(callErr)) |
|
|
|
|
|
|
|
|
log.Error("dialing node_"+id+"fail: ", zap.Error(callErr)) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// RPC call
|
|
|
// RPC call
|
|
|
func (node *Node) ReceiveKV(arg LogIdAndEntry, reply *KVReply) error { |
|
|
func (node *Node) ReceiveKV(arg LogIdAndEntry, reply *KVReply) error { |
|
|
log.Info("node_" + node.selfId + " receive: logId = "+ strconv.Itoa(arg.LogId) + ", key = " + arg.Entry.Key) |
|
|
|
|
|
|
|
|
log.Info("node_" + node.selfId + " receive: logId = " + strconv.Itoa(arg.LogId) + ", key = " + arg.Entry.Key) |
|
|
entry, ok := node.log[arg.LogId] |
|
|
entry, ok := node.log[arg.LogId] |
|
|
if !ok { |
|
|
if !ok { |
|
|
node.log[arg.LogId] = entry |
|
|
node.log[arg.LogId] = entry |
|
@ -86,4 +99,3 @@ func (node *Node) ReceiveKV(arg LogIdAndEntry, reply *KVReply) error { |
|
|
reply.Reply = true // rpc call需要有reply,但实际上调用是否成功是error返回值决定
|
|
|
reply.Reply = true // rpc call需要有reply,但实际上调用是否成功是error返回值决定
|
|
|
return nil |
|
|
return nil |
|
|
} |
|
|
} |
|
|
|
|
|
|