Browse Source

Merge pull request #1446 from tendermint/1442-data-race-fix-attempt

fix data race
pull/1440/head
Ethan Buchman 7 years ago
committed by GitHub
parent
commit
d93e177a69
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 42 additions and 23 deletions
  1. +15
    -5
      consensus/reactor.go
  2. +9
    -4
      consensus/state.go
  3. +0
    -3
      consensus/types/state.go
  4. +13
    -5
      rpc/core/consensus.go
  5. +2
    -3
      rpc/core/pipe.go
  6. +3
    -3
      rpc/core/types/responses.go

+ 15
- 5
consensus/reactor.go View File

@ -9,7 +9,7 @@ import (
"github.com/pkg/errors"
"github.com/tendermint/go-amino"
amino "github.com/tendermint/go-amino"
cmn "github.com/tendermint/tmlibs/common"
"github.com/tendermint/tmlibs/log"
@ -838,8 +838,8 @@ var (
ErrPeerStateInvalidStartTime = errors.New("Error peer state invalid startTime")
)
// PeerState contains the known state of a peer, including its connection
// and threadsafe access to its PeerRoundState.
// PeerState contains the known state of a peer, including its connection and
// threadsafe access to its PeerRoundState.
type PeerState struct {
Peer p2p.Peer
logger log.Logger
@ -878,12 +878,14 @@ func NewPeerState(peer p2p.Peer) *PeerState {
}
}
// SetLogger allows to set a logger on the peer state. Returns the peer state
// itself.
func (ps *PeerState) SetLogger(logger log.Logger) *PeerState {
ps.logger = logger
return ps
}
// GetRoundState returns an atomic snapshot of the PeerRoundState.
// GetRoundState returns an shallow copy of the PeerRoundState.
// There's no point in mutating it since it won't change PeerState.
func (ps *PeerState) GetRoundState() *cstypes.PeerRoundState {
ps.mtx.Lock()
@ -893,6 +895,14 @@ func (ps *PeerState) GetRoundState() *cstypes.PeerRoundState {
return &prs
}
// GetRoundStateJSON returns a json of PeerRoundState, marshalled using go-amino.
func (ps *PeerState) GetRoundStateJSON() ([]byte, error) {
ps.mtx.Lock()
defer ps.mtx.Unlock()
return cdc.MarshalJSON(ps.PeerRoundState)
}
// GetHeight returns an atomic snapshot of the PeerRoundState's height
// used by the mempool to ensure peers are caught up before broadcasting new txs
func (ps *PeerState) GetHeight() int64 {
@ -1055,7 +1065,7 @@ func (ps *PeerState) ensureCatchupCommitRound(height int64, round int, numValida
}
}
// EnsureVoteVitArrays ensures the bit-arrays have been allocated for tracking
// EnsureVoteBitArrays ensures the bit-arrays have been allocated for tracking
// what votes this peer has received.
// NOTE: It's important to make sure that numValidators actually matches
// what the node sees as the number of validators for height.


+ 9
- 4
consensus/state.go View File

@ -168,18 +168,23 @@ func (cs *ConsensusState) GetState() sm.State {
return cs.state.Copy()
}
// GetRoundState returns a copy of the internal consensus state.
// GetRoundState returns a shallow copy of the internal consensus state.
func (cs *ConsensusState) GetRoundState() *cstypes.RoundState {
cs.mtx.Lock()
defer cs.mtx.Unlock()
return cs.getRoundState()
}
func (cs *ConsensusState) getRoundState() *cstypes.RoundState {
rs := cs.RoundState // copy
return &rs
}
// GetRoundStateJSON returns a json of RoundState, marshalled using go-amino.
func (cs *ConsensusState) GetRoundStateJSON() ([]byte, error) {
cs.mtx.Lock()
defer cs.mtx.Unlock()
return cdc.MarshalJSON(cs.RoundState)
}
// GetValidators returns a copy of the current validators.
func (cs *ConsensusState) GetValidators() (int64, []*types.Validator) {
cs.mtx.Lock()


+ 0
- 3
consensus/types/state.go View File

@ -52,9 +52,6 @@ func (rs RoundStepType) String() string {
//-----------------------------------------------------------------------------
// RoundState defines the internal consensus state.
// It is Immutable when returned from ConsensusState.GetRoundState()
// TODO: Actually, only the top pointer is copied,
// so access to field pointers is still racey
// NOTE: Not thread safe. Should only be manipulated by functions downstream
// of the cs.receiveRoutine
type RoundState struct {


+ 13
- 5
rpc/core/consensus.go View File

@ -1,8 +1,9 @@
package core
import (
"encoding/json"
cm "github.com/tendermint/tendermint/consensus"
cstypes "github.com/tendermint/tendermint/consensus/types"
p2p "github.com/tendermint/tendermint/p2p"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
sm "github.com/tendermint/tendermint/state"
@ -58,7 +59,7 @@ func Validators(heightPtr *int64) (*ctypes.ResultValidators, error) {
return &ctypes.ResultValidators{height, validators.Validators}, nil
}
// Dump consensus state.
// DumpConsensusState dumps consensus state.
//
// ```shell
// curl 'localhost:46657/dump_consensus_state'
@ -83,11 +84,18 @@ func Validators(heightPtr *int64) (*ctypes.ResultValidators, error) {
// }
// ```
func DumpConsensusState() (*ctypes.ResultDumpConsensusState, error) {
peerRoundStates := make(map[p2p.ID]*cstypes.PeerRoundState)
peerRoundStates := make(map[p2p.ID]json.RawMessage)
for _, peer := range p2pSwitch.Peers().List() {
peerState := peer.Get(types.PeerStateKey).(*cm.PeerState)
peerRoundState := peerState.GetRoundState()
peerRoundState, err := peerState.GetRoundStateJSON()
if err != nil {
return nil, err
}
peerRoundStates[peer.ID()] = peerRoundState
}
return &ctypes.ResultDumpConsensusState{consensusState.GetRoundState(), peerRoundStates}, nil
roundState, err := consensusState.GetRoundStateJSON()
if err != nil {
return nil, err
}
return &ctypes.ResultDumpConsensusState{roundState, peerRoundStates}, nil
}

+ 2
- 3
rpc/core/pipe.go View File

@ -3,9 +3,8 @@ package core
import (
"time"
"github.com/tendermint/go-crypto"
crypto "github.com/tendermint/go-crypto"
"github.com/tendermint/tendermint/consensus"
cstypes "github.com/tendermint/tendermint/consensus/types"
"github.com/tendermint/tendermint/p2p"
"github.com/tendermint/tendermint/proxy"
sm "github.com/tendermint/tendermint/state"
@ -23,7 +22,7 @@ var subscribeTimeout = 5 * time.Second
type Consensus interface {
GetState() sm.State
GetValidators() (int64, []*types.Validator)
GetRoundState() *cstypes.RoundState
GetRoundStateJSON() ([]byte, error)
}
type P2P interface {


+ 3
- 3
rpc/core/types/responses.go View File

@ -1,6 +1,7 @@
package core_types
import (
"encoding/json"
"strings"
"time"
@ -8,7 +9,6 @@ import (
crypto "github.com/tendermint/go-crypto"
cmn "github.com/tendermint/tmlibs/common"
cstypes "github.com/tendermint/tendermint/consensus/types"
"github.com/tendermint/tendermint/p2p"
"github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
@ -109,8 +109,8 @@ type ResultValidators struct {
}
type ResultDumpConsensusState struct {
RoundState *cstypes.RoundState `json:"round_state"`
PeerRoundStates map[p2p.ID]*cstypes.PeerRoundState `json:"peer_round_states"`
RoundState json.RawMessage `json:"round_state"`
PeerRoundStates map[p2p.ID]json.RawMessage `json:"peer_round_states"`
}
type ResultBroadcastTx struct {


Loading…
Cancel
Save