Skip to content

Commit c0cb011

Browse files
author
Jason Yellick
committed
FAB-10521 Block-cutter should refetch config
The block-cutter is currently instantiated with a reference to the orderer channel config. Once upon a time, each config element was its own mutable state machine, so this worked fine for v1.0.x. However, in v1.1, the individual mutable configs were transformed to be a single immutable config bundle. When the config changes, an entirely new immutable bundle is created and atomically swapped out. Because of this, the block-cutter only retains the reference to the initial immutable blob. It needs to be fixed to pull a fresh reference of the config through the atomic dereference at every block. This CR does just that. Change-Id: I6be1b65cb8d8cc86d5e47da906a127da6651354e Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
1 parent ac462ae commit c0cb011

File tree

5 files changed

+556
-24
lines changed

5 files changed

+556
-24
lines changed

orderer/common/blockcutter/blockcutter.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ func init() {
2222
logger = flogging.MustGetLogger(pkgLogID)
2323
}
2424

25+
type OrdererConfigFetcher interface {
26+
OrdererConfig() (channelconfig.Orderer, bool)
27+
}
28+
2529
// Receiver defines a sink for the ordered broadcast messages
2630
type Receiver interface {
2731
// Ordered should be invoked sequentially as messages are ordered
@@ -35,15 +39,15 @@ type Receiver interface {
3539
}
3640

3741
type receiver struct {
38-
sharedConfigManager channelconfig.Orderer
42+
sharedConfigFetcher OrdererConfigFetcher
3943
pendingBatch []*cb.Envelope
4044
pendingBatchSizeBytes uint32
4145
}
4246

4347
// NewReceiverImpl creates a Receiver implementation based on the given configtxorderer manager
44-
func NewReceiverImpl(sharedConfigManager channelconfig.Orderer) Receiver {
48+
func NewReceiverImpl(sharedConfigFetcher OrdererConfigFetcher) Receiver {
4549
return &receiver{
46-
sharedConfigManager: sharedConfigManager,
50+
sharedConfigFetcher: sharedConfigFetcher,
4751
}
4852
}
4953

@@ -64,9 +68,15 @@ func NewReceiverImpl(sharedConfigManager channelconfig.Orderer) Receiver {
6468
//
6569
// Note that messageBatches can not be greater than 2.
6670
func (r *receiver) Ordered(msg *cb.Envelope) (messageBatches [][]*cb.Envelope, pending bool) {
71+
ordererConfig, ok := r.sharedConfigFetcher.OrdererConfig()
72+
if !ok {
73+
logger.Panicf("Could not retrieve orderer config to query batch parameters, block cutting is not possible")
74+
}
75+
batchSize := ordererConfig.BatchSize()
76+
6777
messageSizeBytes := messageSizeBytes(msg)
68-
if messageSizeBytes > r.sharedConfigManager.BatchSize().PreferredMaxBytes {
69-
logger.Debugf("The current message, with %v bytes, is larger than the preferred batch size of %v bytes and will be isolated.", messageSizeBytes, r.sharedConfigManager.BatchSize().PreferredMaxBytes)
78+
if messageSizeBytes > batchSize.PreferredMaxBytes {
79+
logger.Debugf("The current message, with %v bytes, is larger than the preferred batch size of %v bytes and will be isolated.", messageSizeBytes, batchSize.PreferredMaxBytes)
7080

7181
// cut pending batch, if it has any messages
7282
if len(r.pendingBatch) > 0 {
@@ -80,7 +90,7 @@ func (r *receiver) Ordered(msg *cb.Envelope) (messageBatches [][]*cb.Envelope, p
8090
return
8191
}
8292

83-
messageWillOverflowBatchSizeBytes := r.pendingBatchSizeBytes+messageSizeBytes > r.sharedConfigManager.BatchSize().PreferredMaxBytes
93+
messageWillOverflowBatchSizeBytes := r.pendingBatchSizeBytes+messageSizeBytes > batchSize.PreferredMaxBytes
8494

8595
if messageWillOverflowBatchSizeBytes {
8696
logger.Debugf("The current message, with %v bytes, will overflow the pending batch of %v bytes.", messageSizeBytes, r.pendingBatchSizeBytes)
@@ -94,7 +104,7 @@ func (r *receiver) Ordered(msg *cb.Envelope) (messageBatches [][]*cb.Envelope, p
94104
r.pendingBatchSizeBytes += messageSizeBytes
95105
pending = true
96106

97-
if uint32(len(r.pendingBatch)) >= r.sharedConfigManager.BatchSize().MaxMessageCount {
107+
if uint32(len(r.pendingBatch)) >= batchSize.MaxMessageCount {
98108
logger.Debugf("Batch size met, cutting batch")
99109
messageBatch := r.Cut()
100110
messageBatches = append(messageBatches, messageBatch)

orderer/common/blockcutter/blockcutter_test.go

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,33 @@
11
/*
2-
Copyright IBM Corp. 2016 All Rights Reserved.
2+
Copyright IBM Corp. All Rights Reserved.
33
4-
Licensed under the Apache License, Version 2.0 (the "License");
5-
you may not use this file except in compliance with the License.
6-
You may obtain a copy of the License at
7-
8-
http://www.apache.org/licenses/LICENSE-2.0
9-
10-
Unless required by applicable law or agreed to in writing, software
11-
distributed under the License is distributed on an "AS IS" BASIS,
12-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
See the License for the specific language governing permissions and
14-
limitations under the License.
4+
SPDX-License-Identifier: Apache-2.0
155
*/
166

177
package blockcutter
188

199
import (
2010
"testing"
2111

22-
mockconfig "github.com/hyperledger/fabric/common/mocks/config"
12+
"github.com/hyperledger/fabric/common/channelconfig"
13+
"github.com/hyperledger/fabric/orderer/common/blockcutter/mock"
2314
cb "github.com/hyperledger/fabric/protos/common"
2415
ab "github.com/hyperledger/fabric/protos/orderer"
2516

2617
"github.com/hyperledger/fabric/common/flogging"
2718
"github.com/stretchr/testify/assert"
2819
)
2920

21+
//go:generate counterfeiter -o mock/config_fetcher.go --fake-name OrdererConfigFetcher . ordererConfigFetcher
22+
type ordererConfigFetcher interface {
23+
OrdererConfigFetcher
24+
}
25+
26+
//go:generate counterfeiter -o mock/orderer_config.go --fake-name OrdererConfig . ordererConfig
27+
type ordererConfig interface {
28+
channelconfig.Orderer
29+
}
30+
3031
func init() {
3132
flogging.SetModuleLevel(pkgLogID, "DEBUG")
3233
}
@@ -38,7 +39,17 @@ func TestNormalBatch(t *testing.T) {
3839
maxMessageCount := uint32(2)
3940
absoluteMaxBytes := uint32(1000)
4041
preferredMaxBytes := uint32(100)
41-
r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: absoluteMaxBytes, PreferredMaxBytes: preferredMaxBytes}})
42+
mockConfig := &mock.OrdererConfig{}
43+
mockConfig.BatchSizeReturns(&ab.BatchSize{
44+
MaxMessageCount: maxMessageCount,
45+
AbsoluteMaxBytes: absoluteMaxBytes,
46+
PreferredMaxBytes: preferredMaxBytes,
47+
})
48+
49+
mockConfigFetcher := &mock.OrdererConfigFetcher{}
50+
mockConfigFetcher.OrdererConfigReturns(mockConfig, true)
51+
52+
r := NewReceiverImpl(mockConfigFetcher)
4253

4354
batches, pending := r.Ordered(tx)
4455
assert.Nil(t, batches, "Should not have created batch")
@@ -58,7 +69,17 @@ func TestBatchSizePreferredMaxBytesOverflow(t *testing.T) {
5869
// set message count > 9
5970
maxMessageCount := uint32(20)
6071

61-
r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: preferredMaxBytes * 2, PreferredMaxBytes: preferredMaxBytes}})
72+
mockConfig := &mock.OrdererConfig{}
73+
mockConfig.BatchSizeReturns(&ab.BatchSize{
74+
MaxMessageCount: maxMessageCount,
75+
AbsoluteMaxBytes: preferredMaxBytes * 2,
76+
PreferredMaxBytes: preferredMaxBytes,
77+
})
78+
79+
mockConfigFetcher := &mock.OrdererConfigFetcher{}
80+
mockConfigFetcher.OrdererConfigReturns(mockConfig, true)
81+
82+
r := NewReceiverImpl(mockConfigFetcher)
6283

6384
// enqueue 9 messages
6485
for i := 0; i < 9; i++ {
@@ -89,7 +110,17 @@ func TestBatchSizePreferredMaxBytesOverflowNoPending(t *testing.T) {
89110
// set message count > 1
90111
maxMessageCount := uint32(20)
91112

92-
r := NewReceiverImpl(&mockconfig.Orderer{BatchSizeVal: &ab.BatchSize{MaxMessageCount: maxMessageCount, AbsoluteMaxBytes: preferredMaxBytes * 3, PreferredMaxBytes: preferredMaxBytes}})
113+
mockConfig := &mock.OrdererConfig{}
114+
mockConfig.BatchSizeReturns(&ab.BatchSize{
115+
MaxMessageCount: maxMessageCount,
116+
AbsoluteMaxBytes: preferredMaxBytes * 3,
117+
PreferredMaxBytes: preferredMaxBytes,
118+
})
119+
120+
mockConfigFetcher := &mock.OrdererConfigFetcher{}
121+
mockConfigFetcher.OrdererConfigReturns(mockConfig, true)
122+
123+
r := NewReceiverImpl(mockConfigFetcher)
93124

94125
// submit normal message
95126
batches, pending := r.Ordered(tx)
@@ -105,3 +136,9 @@ func TestBatchSizePreferredMaxBytesOverflowNoPending(t *testing.T) {
105136
assert.Len(t, batch, 1, "Should have had one normal tx in batch %d", i)
106137
}
107138
}
139+
140+
func TestPanicOnMissingConfig(t *testing.T) {
141+
mockConfigFetcher := &mock.OrdererConfigFetcher{}
142+
r := NewReceiverImpl(mockConfigFetcher)
143+
assert.Panics(t, func() { r.Ordered(tx) })
144+
}

orderer/common/blockcutter/mock/config_fetcher.go

Lines changed: 91 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)