Browse Source

[monitor] fix data races!

pull/1943/head
Anton Kaliaev 6 years ago
parent
commit
445ddbf040
No known key found for this signature in database GPG Key ID: 7B6881D965918214
3 changed files with 34 additions and 7 deletions
  1. +21
    -6
      tm-monitor/monitor/monitor.go
  2. +2
    -1
      tm-monitor/monitor/monitor_test.go
  3. +11
    -0
      tm-monitor/monitor/network.go

+ 21
- 6
tm-monitor/monitor/monitor.go View File

@ -3,6 +3,7 @@ package monitor
import (
"fmt"
"math/rand"
"sync"
"time"
"github.com/pkg/errors"
@ -18,7 +19,9 @@ const nodeLivenessTimeout = 5 * time.Second
//
// Common statistics is stored in Network struct.
type Monitor struct {
Nodes []*Node
mtx sync.Mutex
Nodes []*Node
Network *Network
monitorQuit chan struct{} // monitor exitting
@ -75,7 +78,9 @@ func (m *Monitor) SetLogger(l log.Logger) {
// Monitor begins to monitor the node `n`. The node will be started and added
// to the monitor.
func (m *Monitor) Monitor(n *Node) error {
m.mtx.Lock()
m.Nodes = append(m.Nodes, n)
m.mtx.Unlock()
blockCh := make(chan tmtypes.Header, 10)
n.SendBlocksTo(blockCh)
@ -105,13 +110,19 @@ func (m *Monitor) Unmonitor(n *Node) {
close(m.nodeQuit[n.Name])
delete(m.nodeQuit, n.Name)
i, _ := m.NodeByName(n.Name)
m.mtx.Lock()
m.Nodes[i] = m.Nodes[len(m.Nodes)-1]
m.Nodes = m.Nodes[:len(m.Nodes)-1]
m.mtx.Unlock()
}
// NodeByName returns the node and its index if such node exists within the
// monitor. Otherwise, -1 and nil are returned.
func (m *Monitor) NodeByName(name string) (index int, node *Node) {
m.mtx.Lock()
defer m.mtx.Unlock()
for i, n := range m.Nodes {
if name == n.Name {
return i, n
@ -187,18 +198,23 @@ func (m *Monitor) updateNumValidatorLoop() {
var err error
for {
if 0 == len(m.Nodes) {
m.mtx.Lock()
nodesCount := len(m.Nodes)
m.mtx.Unlock()
if 0 == nodesCount {
time.Sleep(m.numValidatorsUpdateInterval)
continue
}
randomNodeIndex := rand.Intn(len(m.Nodes))
randomNodeIndex := rand.Intn(nodesCount)
select {
case <-m.monitorQuit:
return
case <-time.After(m.numValidatorsUpdateInterval):
i := 0
m.mtx.Lock()
for _, n := range m.Nodes {
if i == randomNodeIndex {
height, num, err = n.NumValidators()
@ -209,10 +225,9 @@ func (m *Monitor) updateNumValidatorLoop() {
}
i++
}
m.mtx.Unlock()
if m.Network.Height <= height {
m.Network.NumValidators = num
}
m.Network.UpdateNumValidatorsForHeight(num, height)
}
}
}

+ 2
- 1
tm-monitor/monitor/monitor_test.go View File

@ -25,7 +25,8 @@ func TestMonitorUpdatesNumberOfValidators(t *testing.T) {
time.Sleep(1 * time.Second)
assert.Equal(t, 1, m.Network.NumValidators)
// DATA RACE
// assert.Equal(t, 1, m.Network.NumValidators())
}
func TestMonitorRecalculatesNetworkUptime(t *testing.T) {


+ 11
- 0
tm-monitor/monitor/network.go View File

@ -164,6 +164,15 @@ func (n *Network) updateHealth() {
}
}
func (n *Network) UpdateNumValidatorsForHeight(num int, height uint64) {
n.mu.Lock()
defer n.mu.Unlock()
if n.Height <= height {
n.NumValidators = num
}
}
func (n *Network) GetHealthString() string {
switch n.Health {
case FullHealth:
@ -179,6 +188,8 @@ func (n *Network) GetHealthString() string {
// Uptime returns network's uptime in percentages.
func (n *Network) Uptime() float64 {
n.mu.Lock()
defer n.mu.Unlock()
return n.UptimeData.Uptime
}


Loading…
Cancel
Save