Commit e059219f authored by caopingcp's avatar caopingcp Committed by vipwzw

Query function avoid deadlock

parent aa3cc58a
...@@ -9,7 +9,6 @@ import ( ...@@ -9,7 +9,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"runtime/debug" "runtime/debug"
"sync"
"sync/atomic" "sync/atomic"
"time" "time"
...@@ -17,6 +16,7 @@ import ( ...@@ -17,6 +16,7 @@ import (
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
ttypes "github.com/33cn/plugin/plugin/consensus/qbft/types" ttypes "github.com/33cn/plugin/plugin/consensus/qbft/types"
tmtypes "github.com/33cn/plugin/plugin/dapp/qbftNode/types" tmtypes "github.com/33cn/plugin/plugin/dapp/qbftNode/types"
siasync "github.com/NebulousLabs/Sia/sync"
) )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
...@@ -67,7 +67,7 @@ type ConsensusState struct { ...@@ -67,7 +67,7 @@ type ConsensusState struct {
blockExec *BlockExecutor blockExec *BlockExecutor
// internal state // internal state
mtx sync.Mutex mtx siasync.TryMutex
ttypes.RoundState ttypes.RoundState
state State // QbftState until height-1. state State // QbftState until height-1.
...@@ -145,6 +145,34 @@ func (cs *ConsensusState) IsRunning() bool { ...@@ -145,6 +145,34 @@ func (cs *ConsensusState) IsRunning() bool {
//---------------------------------------- //----------------------------------------
// QueryState returns a copy of the chain state.
func (cs *ConsensusState) QueryState() *State {
if cs == nil {
return nil
}
if !cs.mtx.TryLockTimed(time.Millisecond * 500) {
return nil
}
defer cs.mtx.Unlock()
state := cs.state.Copy()
return &state
}
// QueryRoundState returns a copy of the internal consensus state.
func (cs *ConsensusState) QueryRoundState() *ttypes.RoundState {
if cs == nil {
return nil
}
if !cs.mtx.TryLockTimed(time.Millisecond * 500) {
return nil
}
defer cs.mtx.Unlock()
rs := cs.RoundState
return &rs
}
// GetState returns a copy of the chain state. // GetState returns a copy of the chain state.
func (cs *ConsensusState) GetState() State { func (cs *ConsensusState) GetState() State {
cs.mtx.Lock() cs.mtx.Lock()
......
...@@ -18,7 +18,6 @@ import ( ...@@ -18,7 +18,6 @@ import (
"time" "time"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
ttypes "github.com/33cn/plugin/plugin/consensus/qbft/types" ttypes "github.com/33cn/plugin/plugin/consensus/qbft/types"
tmtypes "github.com/33cn/plugin/plugin/dapp/qbftNode/types" tmtypes "github.com/33cn/plugin/plugin/dapp/qbftNode/types"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
......
...@@ -26,7 +26,7 @@ import ( ...@@ -26,7 +26,7 @@ import (
) )
const ( const (
qbftVersion = "0.1.0" qbftVersion = "0.2.0"
// DefaultQbftPort 默认端口 // DefaultQbftPort 默认端口
DefaultQbftPort = 33001 DefaultQbftPort = 33001
...@@ -665,26 +665,31 @@ func (client *Client) LoadProposalBlock(height int64) *tmtypes.QbftBlock { ...@@ -665,26 +665,31 @@ func (client *Client) LoadProposalBlock(height int64) *tmtypes.QbftBlock {
// Query_IsHealthy query whether consensus is sync // Query_IsHealthy query whether consensus is sync
func (client *Client) Query_IsHealthy(req *types.ReqNil) (types.Message, error) { func (client *Client) Query_IsHealthy(req *types.ReqNil) (types.Message, error) {
isHealthy := false isHealthy := false
if client.IsCaughtUp() && client.GetCurrentHeight() <= client.csState.GetRoundState().Height+1 { if client.IsCaughtUp() {
isHealthy = true rs := client.csState.QueryRoundState()
if rs != nil && client.GetCurrentHeight() <= rs.Height+1 {
isHealthy = true
}
} }
return &tmtypes.QbftIsHealthy{IsHealthy: isHealthy}, nil return &tmtypes.QbftIsHealthy{IsHealthy: isHealthy}, nil
} }
// Query_CurrentState query current consensus state // Query_CurrentState query current consensus state
func (client *Client) Query_CurrentState(req *types.ReqNil) (types.Message, error) { func (client *Client) Query_CurrentState(req *types.ReqNil) (types.Message, error) {
if client.csState == nil { state := client.csState.QueryState()
return nil, ttypes.ErrConsensusState if state == nil {
return nil, ttypes.ErrConsensusQuery
} }
return SaveState(client.csState.GetState()), nil return SaveState(*state), nil
} }
// Query_NodeInfo query validator node info // Query_NodeInfo query validator node info
func (client *Client) Query_NodeInfo(req *types.ReqNil) (types.Message, error) { func (client *Client) Query_NodeInfo(req *types.ReqNil) (types.Message, error) {
if client.csState == nil { rs := client.csState.QueryRoundState()
return nil, ttypes.ErrConsensusState if rs == nil {
return nil, ttypes.ErrConsensusQuery
} }
vals := client.csState.GetRoundState().Validators.Validators vals := rs.Validators.Validators
nodes := make([]*tmtypes.QbftNodeInfo, 0) nodes := make([]*tmtypes.QbftNodeInfo, 0)
for _, val := range vals { for _, val := range vals {
if val == nil { if val == nil {
......
...@@ -29,7 +29,7 @@ var ( ...@@ -29,7 +29,7 @@ var (
// ErrLastBlockID error type // ErrLastBlockID error type
ErrLastBlockID = errors.New("ErrLastBlockID") ErrLastBlockID = errors.New("ErrLastBlockID")
// ErrConsensusState error type // ErrConsensusState error type
ErrConsensusState = errors.New("ErrConsensusState") ErrConsensusQuery = errors.New("Consensus is busy, please try again!")
) )
var ( var (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment