-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.go
113 lines (103 loc) · 2.86 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*
* Copyright 2019 Insolar Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package manager
import (
"github.com/blang/semver"
"github.com/insolar/insolar/core"
"github.com/insolar/insolar/log"
"github.com/insolar/insolar/version"
"github.com/pkg/errors"
)
func ProcessVersionConsensus(nodes []core.Node) error {
if len(nodes) == 0 {
return errors.New("List of nodes is empty")
}
mapOfVersions := getMapOfVersion(nodes)
topVersion, err := getMaxVersion(getRequired(len(nodes)), mapOfVersions)
if err != nil {
return err
}
vm, err := GetVersionManager()
if err != nil {
return err
}
currentVersion, err := ParseVersion(version.Version)
if err != nil {
return errors.New("current version is invalid: " + err.Error())
}
if currentVersion.Compare(*topVersion) != 0 {
log.Warn("WARNING! Current version: " + StringVersion(currentVersion) + ", must go to version: " + StringVersion(topVersion))
}
vm.AgreedVersion = topVersion
return nil
}
func getMapOfVersion(nodes []core.Node) *map[string]int {
mapOfVersions := make(map[string]int)
for _, node := range nodes {
ver := node.Version()
if _, ok := mapOfVersions[ver]; ok {
mapOfVersions[ver]++
} else {
mapOfVersions[ver] = 1
}
}
return &mapOfVersions
}
func getMaxVersion(required int, mapOfVersions *map[string]int) (*semver.Version, error) {
versions := make([]semver.Version, 0, len(*mapOfVersions))
for version := range *mapOfVersions {
semVer, err := ParseVersion(version)
if err != nil {
log.Warn("Error parsing version: " + version)
}
if semVer != nil {
versions = append(versions, *semVer)
}
}
semver.Sort(versions)
count := 0
for i := len(versions) - 1; i >= 0; i-- {
key := StringVersion(&versions[i])
count += (*mapOfVersions)[key]
if count >= required {
return &versions[i], nil
}
}
return nil, errors.New("Version consensus is not reached")
}
func Verify(key string) bool {
vm, err := GetVersionManager()
if err != nil {
return false
}
return vm.IsAvailable(key)
}
func getRequired(count int) int {
return count/2 + 1
}
func ParseVersion(ver string) (*semver.Version, error) {
if ver == "unset" {
return semver.New("0.0.0")
}
version, err := semver.ParseTolerant(ver)
if err != nil {
return nil, err
}
return &version, nil
}
func StringVersion(ver *semver.Version) string {
return "v" + ver.String()
}