[#100] netmap: Make AddPeer stable for simultaneous invocations in one block

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
Alex Vanin 2021-06-29 21:15:53 +03:00 committed by Alex Vanin
parent af21f33657
commit 0b04200815

View file

@ -56,6 +56,7 @@ const (
var ( var (
configPrefix = []byte("config") configPrefix = []byte("config")
candidatePrefix = []byte("candidate")
) )
// _deploy function sets up initial list of inner ring public keys. // _deploy function sets up initial list of inner ring public keys.
@ -208,8 +209,6 @@ func AddPeer(nodeInfo []byte) {
info: nodeInfo, info: nodeInfo,
} }
nm := addToNetmap(ctx, candidate)
if notaryDisabled { if notaryDisabled {
threshold := len(alphabet)*2/3 + 1 threshold := len(alphabet)*2/3 + 1
rawCandidate := std.Serialize(candidate) rawCandidate := std.Serialize(candidate)
@ -223,12 +222,7 @@ func AddPeer(nodeInfo []byte) {
common.RemoveVotes(ctx, id) common.RemoveVotes(ctx, id)
} }
if nm == nil { addToNetmap(ctx, candidate)
runtime.Log("addPeer: storage node already in the netmap")
} else {
common.SetSerialized(ctx, netmapKey, nm)
runtime.Log("addPeer: add storage node to the network map")
}
} }
func UpdateState(state int, publicKey interop.PublicKey) { func UpdateState(state int, publicKey interop.PublicKey) {
@ -278,9 +272,8 @@ func UpdateState(state int, publicKey interop.PublicKey) {
switch nodeState(state) { switch nodeState(state) {
case offlineState: case offlineState:
newNetmap := removeFromNetmap(ctx, publicKey) removeFromNetmap(ctx, publicKey)
runtime.Log("updateState: remove storage node from the network map") runtime.Log("updateState: remove storage node from the network map")
common.SetSerialized(ctx, netmapKey, newNetmap)
default: default:
panic("updateState: unsupported state") panic("updateState: unsupported state")
} }
@ -473,49 +466,29 @@ func Version() int {
return version return version
} }
func addToNetmap(ctx storage.Context, n storageNode) []netmapNode { func addToNetmap(ctx storage.Context, n storageNode) {
var ( var (
newNode = n.info newNode = n.info
newNodeKey = newNode[2:35] newNodeKey = newNode[2:35]
storageKey = append(candidatePrefix, newNodeKey...)
netmap = getNetmapNodes(ctx)
node = netmapNode{ node = netmapNode{
node: n, node: n,
state: onlineState, state: onlineState,
} }
) )
for i := range netmap { data := storage.Get(ctx, storageKey)
netmapNode := netmap[i].node.info if data != nil {
netmapNodeKey := netmapNode[2:35] return
if common.BytesEqual(newNodeKey, netmapNodeKey) {
return nil
}
} }
netmap = append(netmap, node) storage.Put(ctx, storageKey, std.Serialize(node))
return netmap
} }
func removeFromNetmap(ctx storage.Context, key interop.PublicKey) []netmapNode { func removeFromNetmap(ctx storage.Context, key interop.PublicKey) {
var ( storageKey := append(candidatePrefix, key...)
netmap = getNetmapNodes(ctx) storage.Delete(ctx, storageKey)
newNetmap = []netmapNode{}
)
for i := 0; i < len(netmap); i++ {
item := netmap[i]
node := item.node.info
publicKey := node[2:35] // offset:2, len:33
if !common.BytesEqual(publicKey, key) {
newNetmap = append(newNetmap, item)
}
}
return newNetmap
} }
func filterNetmap(ctx storage.Context, st nodeState) []storageNode { func filterNetmap(ctx storage.Context, st nodeState) []storageNode {
@ -535,12 +508,16 @@ func filterNetmap(ctx storage.Context, st nodeState) []storageNode {
} }
func getNetmapNodes(ctx storage.Context) []netmapNode { func getNetmapNodes(ctx storage.Context) []netmapNode {
data := storage.Get(ctx, netmapKey) result := []netmapNode{}
if data != nil {
return std.Deserialize(data.([]byte)).([]netmapNode) it := storage.Find(ctx, candidatePrefix, storage.ValuesOnly)
for iterator.Next(it) {
rawNode := iterator.Value(it).([]byte)
node := std.Deserialize(rawNode).(netmapNode)
result = append(result, node)
} }
return []netmapNode{} return result
} }
func getSnapshot(ctx storage.Context, key string) []storageNode { func getSnapshot(ctx storage.Context, key string) []storageNode {