Fetch the repository succeeded.
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package solo
import (
"fmt"
"time"
cb "github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/orderer/consensus"
)
var logger = flogging.MustGetLogger("orderer.consensus.solo")
type consenter struct{}
type chain struct {
support consensus.ConsenterSupport
sendChan chan *message
exitChan chan struct{}
}
type message struct {
configSeq uint64
normalMsg *cb.Envelope
configMsg *cb.Envelope
}
// New creates a new consenter for the solo consensus scheme.
// The solo consensus scheme is very simple, and allows only one consenter for a given chain (this process).
// It accepts messages being delivered via Order/Configure, orders them, and then uses the blockcutter to form the messages
// into blocks before writing to the given ledger
func New() consensus.Consenter {
return &consenter{}
}
func (solo *consenter) HandleChain(support consensus.ConsenterSupport, metadata *cb.Metadata) (consensus.Chain, error) {
logger.Warningf("Use of the Solo orderer is deprecated and remains only for use in test environments but may be removed in the future.")
return newChain(support), nil
}
func newChain(support consensus.ConsenterSupport) *chain {
return &chain{
support: support,
sendChan: make(chan *message),
exitChan: make(chan struct{}),
}
}
func (ch *chain) Start() {
go ch.main()
}
func (ch *chain) Halt() {
select {
case <-ch.exitChan:
// Allow multiple halts without panic
default:
close(ch.exitChan)
}
}
func (ch *chain) WaitReady() error {
return nil
}
// Order accepts normal messages for ordering
func (ch *chain) Order(env *cb.Envelope, configSeq uint64) error {
select {
case ch.sendChan <- &message{
configSeq: configSeq,
normalMsg: env,
}:
return nil
case <-ch.exitChan:
return fmt.Errorf("Exiting")
}
}
// Configure accepts configuration update messages for ordering
func (ch *chain) Configure(config *cb.Envelope, configSeq uint64) error {
select {
case ch.sendChan <- &message{
configSeq: configSeq,
configMsg: config,
}:
return nil
case <-ch.exitChan:
return fmt.Errorf("Exiting")
}
}
// Errored only closes on exit
func (ch *chain) Errored() <-chan struct{} {
return ch.exitChan
}
func (ch *chain) main() {
var timer <-chan time.Time
var err error
for {
seq := ch.support.Sequence()
err = nil
select {
case msg := <-ch.sendChan:
if msg.configMsg == nil {
// NormalMsg
if msg.configSeq < seq {
_, err = ch.support.ProcessNormalMsg(msg.normalMsg)
if err != nil {
logger.Warningf("Discarding bad normal message: %s", err)
continue
}
}
batches, pending := ch.support.BlockCutter().Ordered(msg.normalMsg)
for _, batch := range batches {
block := ch.support.CreateNextBlock(batch)
ch.support.WriteBlock(block, nil)
}
switch {
case timer != nil && !pending:
// Timer is already running but there are no messages pending, stop the timer
timer = nil
case timer == nil && pending:
// Timer is not already running and there are messages pending, so start it
timer = time.After(ch.support.SharedConfig().BatchTimeout())
logger.Debugf("Just began %s batch timer", ch.support.SharedConfig().BatchTimeout().String())
default:
// Do nothing when:
// 1. Timer is already running and there are messages pending
// 2. Timer is not set and there are no messages pending
}
} else {
// ConfigMsg
if msg.configSeq < seq {
msg.configMsg, _, err = ch.support.ProcessConfigMsg(msg.configMsg)
if err != nil {
logger.Warningf("Discarding bad config message: %s", err)
continue
}
}
batch := ch.support.BlockCutter().Cut()
if batch != nil {
block := ch.support.CreateNextBlock(batch)
ch.support.WriteBlock(block, nil)
}
block := ch.support.CreateNextBlock([]*cb.Envelope{msg.configMsg})
ch.support.WriteConfigBlock(block, nil)
timer = nil
}
case <-timer:
//clear the timer
timer = nil
batch := ch.support.BlockCutter().Cut()
if len(batch) == 0 {
logger.Warningf("Batch timer expired with no pending requests, this might indicate a bug")
continue
}
logger.Debugf("Batch timer expired, creating block")
block := ch.support.CreateNextBlock(batch)
ch.support.WriteBlock(block, nil)
case <-ch.exitChan:
logger.Debugf("Exiting")
return
}
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。