Browse Source

BitArray takes a pointer receiver. More logging

pull/67/head
Jae Kwon 10 years ago
parent
commit
da73e001ad
6 changed files with 59 additions and 55 deletions
  1. +25
    -27
      common/bit_array.go
  2. +1
    -1
      common/bit_array_test.go
  3. +25
    -19
      consensus/reactor.go
  4. +3
    -3
      consensus/vote_set.go
  5. +3
    -3
      types/block.go
  6. +2
    -2
      types/part_set.go

+ 25
- 27
common/bit_array.go View File

@ -13,30 +13,26 @@ type BitArray struct {
Elems []uint64 // NOTE: persisted via reflect, must be exported Elems []uint64 // NOTE: persisted via reflect, must be exported
} }
func NewBitArray(bits uint) BitArray {
return BitArray{
func NewBitArray(bits uint) *BitArray {
return &BitArray{
Bits: bits, Bits: bits,
Elems: make([]uint64, (bits+63)/64), Elems: make([]uint64, (bits+63)/64),
} }
} }
func (bA BitArray) Size() uint {
func (bA *BitArray) Size() uint {
return bA.Bits return bA.Bits
} }
func (bA BitArray) IsZero() bool {
return bA.Bits == 0
}
// NOTE: behavior is undefined if i >= bA.Bits // NOTE: behavior is undefined if i >= bA.Bits
func (bA BitArray) GetIndex(i uint) bool {
func (bA *BitArray) GetIndex(i uint) bool {
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock() defer bA.mtx.Unlock()
return bA.getIndex(i) return bA.getIndex(i)
} }
func (bA BitArray) getIndex(i uint) bool {
func (bA *BitArray) getIndex(i uint) bool {
if i >= bA.Bits { if i >= bA.Bits {
return false return false
} }
@ -44,15 +40,14 @@ func (bA BitArray) getIndex(i uint) bool {
} }
// NOTE: behavior is undefined if i >= bA.Bits // NOTE: behavior is undefined if i >= bA.Bits
func (bA BitArray) SetIndex(i uint, v bool) bool {
func (bA *BitArray) SetIndex(i uint, v bool) bool {
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock() defer bA.mtx.Unlock()
return bA.setIndex(i, v) return bA.setIndex(i, v)
} }
func (bA BitArray) setIndex(i uint, v bool) bool {
func (bA *BitArray) setIndex(i uint, v bool) bool {
if i >= bA.Bits { if i >= bA.Bits {
return false return false
} }
@ -64,32 +59,32 @@ func (bA BitArray) setIndex(i uint, v bool) bool {
return true return true
} }
func (bA BitArray) Copy() BitArray {
func (bA *BitArray) Copy() *BitArray {
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock() defer bA.mtx.Unlock()
return bA.copy() return bA.copy()
} }
func (bA BitArray) copy() BitArray {
func (bA *BitArray) copy() *BitArray {
c := make([]uint64, len(bA.Elems)) c := make([]uint64, len(bA.Elems))
copy(c, bA.Elems) copy(c, bA.Elems)
return BitArray{
return &BitArray{
Bits: bA.Bits, Bits: bA.Bits,
Elems: c, Elems: c,
} }
} }
func (bA BitArray) copyBits(bits uint) BitArray {
func (bA *BitArray) copyBits(bits uint) *BitArray {
c := make([]uint64, (bits+63)/64) c := make([]uint64, (bits+63)/64)
copy(c, bA.Elems) copy(c, bA.Elems)
return BitArray{
return &BitArray{
Bits: bits, Bits: bits,
Elems: c, Elems: c,
} }
} }
// Returns a BitArray of larger bits size. // Returns a BitArray of larger bits size.
func (bA BitArray) Or(o BitArray) BitArray {
func (bA *BitArray) Or(o *BitArray) *BitArray {
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock() defer bA.mtx.Unlock()
@ -101,14 +96,14 @@ func (bA BitArray) Or(o BitArray) BitArray {
} }
// Returns a BitArray of smaller bit size. // Returns a BitArray of smaller bit size.
func (bA BitArray) And(o BitArray) BitArray {
func (bA *BitArray) And(o *BitArray) *BitArray {
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock() defer bA.mtx.Unlock()
return bA.and(o) return bA.and(o)
} }
func (bA BitArray) and(o BitArray) BitArray {
func (bA *BitArray) and(o *BitArray) *BitArray {
c := bA.copyBits(MinUint(bA.Bits, o.Bits)) c := bA.copyBits(MinUint(bA.Bits, o.Bits))
for i := 0; i < len(c.Elems); i++ { for i := 0; i < len(c.Elems); i++ {
c.Elems[i] &= o.Elems[i] c.Elems[i] &= o.Elems[i]
@ -116,7 +111,7 @@ func (bA BitArray) and(o BitArray) BitArray {
return c return c
} }
func (bA BitArray) Not() BitArray {
func (bA *BitArray) Not() *BitArray {
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock() defer bA.mtx.Unlock()
@ -127,7 +122,7 @@ func (bA BitArray) Not() BitArray {
return c return c
} }
func (bA BitArray) Sub(o BitArray) BitArray {
func (bA *BitArray) Sub(o *BitArray) *BitArray {
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock() defer bA.mtx.Unlock()
@ -148,7 +143,7 @@ func (bA BitArray) Sub(o BitArray) BitArray {
} }
} }
func (bA BitArray) IsFull() bool {
func (bA *BitArray) IsFull() bool {
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock() defer bA.mtx.Unlock()
@ -169,7 +164,7 @@ func (bA BitArray) IsFull() bool {
return (lastElem+1)&((uint64(1)<<lastElemBits)-1) == 0 return (lastElem+1)&((uint64(1)<<lastElemBits)-1) == 0
} }
func (bA BitArray) PickRandom() (uint, bool) {
func (bA *BitArray) PickRandom() (uint, bool) {
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock() defer bA.mtx.Unlock()
@ -209,20 +204,23 @@ func (bA BitArray) PickRandom() (uint, bool) {
return 0, false return 0, false
} }
func (bA BitArray) String() string {
func (bA *BitArray) String() string {
if bA == nil {
return "nil-BitArray"
}
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock() defer bA.mtx.Unlock()
return bA.stringIndented("") return bA.stringIndented("")
} }
func (bA BitArray) StringIndented(indent string) string {
func (bA *BitArray) StringIndented(indent string) string {
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock() defer bA.mtx.Unlock()
return bA.StringIndented(indent) return bA.StringIndented(indent)
} }
func (bA BitArray) stringIndented(indent string) string {
func (bA *BitArray) stringIndented(indent string) string {
lines := []string{} lines := []string{}
bits := "" bits := ""


+ 1
- 1
common/bit_array_test.go View File

@ -4,7 +4,7 @@ import (
"testing" "testing"
) )
func randBitArray(bits uint) (BitArray, []byte) {
func randBitArray(bits uint) (*BitArray, []byte) {
src := RandBytes(int((bits + 7) / 8)) src := RandBytes(int((bits + 7) / 8))
bA := NewBitArray(bits) bA := NewBitArray(bits)
for i := uint(0); i < uint(len(src)); i++ { for i := uint(0); i < uint(len(src)); i++ {


+ 25
- 19
consensus/reactor.go View File

@ -442,7 +442,7 @@ OUTER_LOOP:
sleeping = 0 sleeping = 0
} }
trySendVote := func(voteSet *VoteSet, peerVoteSet BitArray) (sent bool) {
trySendVote := func(voteSet *VoteSet, peerVoteSet *BitArray) (sent bool) {
if prs.Height == voteSet.Height() { if prs.Height == voteSet.Height() {
// Initialize Prevotes/Precommits/Commits if needed // Initialize Prevotes/Precommits/Commits if needed
ps.EnsureVoteBitArrays(prs.Height, voteSet.Size()) ps.EnsureVoteBitArrays(prs.Height, voteSet.Size())
@ -460,7 +460,7 @@ OUTER_LOOP:
return false return false
} }
trySendCommitFromValidation := func(blockMeta *types.BlockMeta, validation *types.Validation, peerVoteSet BitArray) (sent bool) {
trySendCommitFromValidation := func(blockMeta *types.BlockMeta, validation *types.Validation, peerVoteSet *BitArray) (sent bool) {
// Initialize Commits if needed // Initialize Commits if needed
ps.EnsureVoteBitArrays(prs.Height, uint(len(validation.Commits))) ps.EnsureVoteBitArrays(prs.Height, uint(len(validation.Commits)))
@ -588,13 +588,13 @@ type PeerRoundState struct {
StartTime time.Time // Estimated start of round 0 at this height StartTime time.Time // Estimated start of round 0 at this height
Proposal bool // True if peer has proposal for this round Proposal bool // True if peer has proposal for this round
ProposalBlockParts types.PartSetHeader // ProposalBlockParts types.PartSetHeader //
ProposalBlockBitArray BitArray // True bit -> has part
ProposalBlockBitArray *BitArray // True bit -> has part
ProposalPOLParts types.PartSetHeader // ProposalPOLParts types.PartSetHeader //
ProposalPOLBitArray BitArray // True bit -> has part
Prevotes BitArray // All votes peer has for this round
Precommits BitArray // All precommits peer has for this round
Commits BitArray // All commits peer has for this height
LastCommits BitArray // All commits peer has for last height
ProposalPOLBitArray *BitArray // True bit -> has part
Prevotes *BitArray // All votes peer has for this round
Precommits *BitArray // All precommits peer has for this round
Commits *BitArray // All commits peer has for this height
LastCommits *BitArray // All commits peer has for last height
HasAllCatchupCommits bool // Used for catch-up HasAllCatchupCommits bool // Used for catch-up
} }
@ -606,12 +606,14 @@ var (
) )
type PeerState struct { type PeerState struct {
Key string
mtx sync.Mutex mtx sync.Mutex
PeerRoundState PeerRoundState
} }
func NewPeerState(peer *p2p.Peer) *PeerState { func NewPeerState(peer *p2p.Peer) *PeerState {
return &PeerState{}
return &PeerState{Key: peer.Key}
} }
// Returns an atomic snapshot of the PeerRoundState. // Returns an atomic snapshot of the PeerRoundState.
@ -672,13 +674,13 @@ func (ps *PeerState) EnsureVoteBitArrays(height uint, numValidators uint) {
return return
} }
if ps.Prevotes.IsZero() {
if ps.Prevotes == nil {
ps.Prevotes = NewBitArray(numValidators) ps.Prevotes = NewBitArray(numValidators)
} }
if ps.Precommits.IsZero() {
if ps.Precommits == nil {
ps.Precommits = NewBitArray(numValidators) ps.Precommits = NewBitArray(numValidators)
} }
if ps.Commits.IsZero() {
if ps.Commits == nil {
ps.Commits = NewBitArray(numValidators) ps.Commits = NewBitArray(numValidators)
} }
} }
@ -694,6 +696,7 @@ func (ps *PeerState) setHasVote(height uint, round uint, type_ byte, index uint)
if ps.Height == height+1 && type_ == types.VoteTypeCommit { if ps.Height == height+1 && type_ == types.VoteTypeCommit {
// Special case for LastCommits. // Special case for LastCommits.
ps.LastCommits.SetIndex(index, true) ps.LastCommits.SetIndex(index, true)
log.Debug("SetHasVote", "lastCommits", ps.LastCommits, "index", index)
return return
} else if ps.Height != height { } else if ps.Height != height {
// Does not apply. // Does not apply.
@ -703,14 +706,17 @@ func (ps *PeerState) setHasVote(height uint, round uint, type_ byte, index uint)
switch type_ { switch type_ {
case types.VoteTypePrevote: case types.VoteTypePrevote:
ps.Prevotes.SetIndex(index, true) ps.Prevotes.SetIndex(index, true)
log.Debug("SetHasVote", "peer", ps.Key, "prevotes", ps.Prevotes, "index", index)
case types.VoteTypePrecommit: case types.VoteTypePrecommit:
ps.Precommits.SetIndex(index, true) ps.Precommits.SetIndex(index, true)
log.Debug("SetHasVote", "peer", ps.Key, "precommits", ps.Precommits, "index", index)
case types.VoteTypeCommit: case types.VoteTypeCommit:
if round < ps.Round { if round < ps.Round {
ps.Prevotes.SetIndex(index, true) ps.Prevotes.SetIndex(index, true)
ps.Precommits.SetIndex(index, true) ps.Precommits.SetIndex(index, true)
} }
ps.Commits.SetIndex(index, true) ps.Commits.SetIndex(index, true)
log.Debug("SetHasVote", "peer", ps.Key, "commits", ps.Commits, "index", index)
default: default:
panic("Invalid vote type") panic("Invalid vote type")
} }
@ -744,22 +750,22 @@ func (ps *PeerState) ApplyNewRoundStepMessage(msg *NewRoundStepMessage, rs *Roun
if psHeight != msg.Height || psRound != msg.Round { if psHeight != msg.Height || psRound != msg.Round {
ps.Proposal = false ps.Proposal = false
ps.ProposalBlockParts = types.PartSetHeader{} ps.ProposalBlockParts = types.PartSetHeader{}
ps.ProposalBlockBitArray = BitArray{}
ps.ProposalBlockBitArray = nil
ps.ProposalPOLParts = types.PartSetHeader{} ps.ProposalPOLParts = types.PartSetHeader{}
ps.ProposalPOLBitArray = BitArray{}
ps.ProposalPOLBitArray = nil
// We'll update the BitArray capacity later. // We'll update the BitArray capacity later.
ps.Prevotes = BitArray{}
ps.Precommits = BitArray{}
ps.Prevotes = nil
ps.Precommits = nil
} }
if psHeight != msg.Height { if psHeight != msg.Height {
// Shift Commits to LastCommits // Shift Commits to LastCommits
if psHeight+1 == msg.Height { if psHeight+1 == msg.Height {
ps.LastCommits = ps.Commits ps.LastCommits = ps.Commits
} else { } else {
ps.LastCommits = BitArray{}
ps.LastCommits = nil
} }
// We'll update the BitArray capacity later. // We'll update the BitArray capacity later.
ps.Commits = BitArray{}
ps.Commits = nil
ps.HasAllCatchupCommits = false ps.HasAllCatchupCommits = false
} }
} }
@ -842,7 +848,7 @@ func (m *NewRoundStepMessage) String() string {
type CommitStepMessage struct { type CommitStepMessage struct {
Height uint Height uint
BlockParts types.PartSetHeader BlockParts types.PartSetHeader
BlockBitArray BitArray
BlockBitArray *BitArray
} }
func (m *CommitStepMessage) String() string { func (m *CommitStepMessage) String() string {


+ 3
- 3
consensus/vote_set.go View File

@ -26,7 +26,7 @@ type VoteSet struct {
mtx sync.Mutex mtx sync.Mutex
valSet *sm.ValidatorSet valSet *sm.ValidatorSet
votes []*types.Vote // validator index -> vote votes []*types.Vote // validator index -> vote
votesBitArray BitArray // validator index -> has vote?
votesBitArray *BitArray // validator index -> has vote?
votesByBlock map[string]uint64 // string(blockHash)+string(blockParts) -> vote sum. votesByBlock map[string]uint64 // string(blockHash)+string(blockParts) -> vote sum.
totalVotes uint64 totalVotes uint64
maj23Hash []byte maj23Hash []byte
@ -148,9 +148,9 @@ func (voteSet *VoteSet) AddFromCommits(commits *VoteSet) {
} }
} }
func (voteSet *VoteSet) BitArray() BitArray {
func (voteSet *VoteSet) BitArray() *BitArray {
if voteSet == nil { if voteSet == nil {
return BitArray{}
return nil
} }
voteSet.mtx.Lock() voteSet.mtx.Lock()
defer voteSet.mtx.Unlock() defer voteSet.mtx.Unlock()


+ 3
- 3
types/block.go View File

@ -201,7 +201,7 @@ type Validation struct {
// Volatile // Volatile
hash []byte hash []byte
bitArray BitArray
bitArray *BitArray
} }
func (v *Validation) ValidateBasic() error { func (v *Validation) ValidateBasic() error {
@ -254,8 +254,8 @@ func (v *Validation) StringIndented(indent string) string {
indent, v.hash) indent, v.hash)
} }
func (v *Validation) BitArray() BitArray {
if v.bitArray.IsZero() {
func (v *Validation) BitArray() *BitArray {
if v.bitArray == nil {
v.bitArray = NewBitArray(uint(len(v.Commits))) v.bitArray = NewBitArray(uint(len(v.Commits)))
for i, commit := range v.Commits { for i, commit := range v.Commits {
v.bitArray.SetIndex(uint(i), !commit.IsZero()) v.bitArray.SetIndex(uint(i), !commit.IsZero())


+ 2
- 2
types/part_set.go View File

@ -97,7 +97,7 @@ type PartSet struct {
mtx sync.Mutex mtx sync.Mutex
parts []*Part parts []*Part
partsBitArray BitArray
partsBitArray *BitArray
count uint count uint
} }
@ -162,7 +162,7 @@ func (ps *PartSet) HasHeader(header PartSetHeader) bool {
} }
} }
func (ps *PartSet) BitArray() BitArray {
func (ps *PartSet) BitArray() *BitArray {
ps.mtx.Lock() ps.mtx.Lock()
defer ps.mtx.Unlock() defer ps.mtx.Unlock()
return ps.partsBitArray.Copy() return ps.partsBitArray.Copy()


Loading…
Cancel
Save