Skip to content

Commit 5659656

Browse files
author
Luis Sanchez
committed
Apply QueueSize on a per-client basis.
FAB-507 https://jira.hyperledger.org/browse/FAB-507 The implementation of the solo orderer has a send queue of size QueueSize that is shared amoungst all clients. This changeset provides each client with it's own send queue of size QueueSize. Change-Id: I2ecb690f484ba1e531c99c3f5e6ff046239cb0a0 Signed-off-by: Luis Sanchez <[email protected]>
1 parent 801f1e4 commit 5659656

File tree

2 files changed

+82
-6
lines changed

2 files changed

+82
-6
lines changed

orderer/solo/broadcast.go

+46-4
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ import (
2424
)
2525

2626
type broadcastServer struct {
27-
queue chan *ab.BroadcastMessage
27+
queueSize int
2828
batchSize int
2929
batchTimeout time.Duration
3030
rl rawledger.Writer
31+
sendChan chan *ab.BroadcastMessage
3132
exitChan chan struct{}
3233
}
3334

@@ -39,10 +40,11 @@ func newBroadcastServer(queueSize, batchSize int, batchTimeout time.Duration, rl
3940

4041
func newPlainBroadcastServer(queueSize, batchSize int, batchTimeout time.Duration, rl rawledger.Writer) *broadcastServer {
4142
bs := &broadcastServer{
42-
queue: make(chan *ab.BroadcastMessage, queueSize),
43+
queueSize: queueSize,
4344
batchSize: batchSize,
4445
batchTimeout: batchTimeout,
4546
rl: rl,
47+
sendChan: make(chan *ab.BroadcastMessage),
4648
exitChan: make(chan struct{}),
4749
}
4850
return bs
@@ -59,7 +61,7 @@ outer:
5961
timer := time.After(bs.batchTimeout)
6062
for {
6163
select {
62-
case msg := <-bs.queue:
64+
case msg := <-bs.sendChan:
6365
curBatch = append(curBatch, msg)
6466
if len(curBatch) < bs.batchSize {
6567
continue
@@ -83,6 +85,38 @@ outer:
8385
}
8486

8587
func (bs *broadcastServer) handleBroadcast(srv ab.AtomicBroadcast_BroadcastServer) error {
88+
b := newBroadcaster(bs)
89+
defer close(b.queue)
90+
go b.drainQueue()
91+
return b.queueBroadcastMessages(srv)
92+
}
93+
94+
type broadcaster struct {
95+
bs *broadcastServer
96+
queue chan *ab.BroadcastMessage
97+
}
98+
99+
func (b *broadcaster) drainQueue() {
100+
for {
101+
select {
102+
case msg, ok := <-b.queue:
103+
if ok {
104+
select {
105+
case b.bs.sendChan <- msg:
106+
case <-b.bs.exitChan:
107+
return
108+
}
109+
} else {
110+
return
111+
}
112+
case <-b.bs.exitChan:
113+
return
114+
}
115+
}
116+
}
117+
118+
func (b *broadcaster) queueBroadcastMessages(srv ab.AtomicBroadcast_BroadcastServer) error {
119+
86120
for {
87121
msg, err := srv.Recv()
88122
if err != nil {
@@ -97,7 +131,7 @@ func (bs *broadcastServer) handleBroadcast(srv ab.AtomicBroadcast_BroadcastServe
97131
}
98132

99133
select {
100-
case bs.queue <- msg:
134+
case b.queue <- msg:
101135
err = srv.Send(&ab.BroadcastResponse{ab.Status_SUCCESS})
102136
default:
103137
err = srv.Send(&ab.BroadcastResponse{ab.Status_SERVICE_UNAVAILABLE})
@@ -108,3 +142,11 @@ func (bs *broadcastServer) handleBroadcast(srv ab.AtomicBroadcast_BroadcastServe
108142
}
109143
}
110144
}
145+
146+
func newBroadcaster(bs *broadcastServer) *broadcaster {
147+
b := &broadcaster{
148+
bs: bs,
149+
queue: make(chan *ab.BroadcastMessage, bs.queueSize),
150+
}
151+
return b
152+
}

orderer/solo/broadcast_test.go

+36-2
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,12 @@ func (m *mockB) Recv() (*ab.BroadcastMessage, error) {
5757
func TestQueueOverflow(t *testing.T) {
5858
bs := newPlainBroadcastServer(2, 1, time.Second, nil) // queueSize, batchSize (unused), batchTimeout (unused), ramLedger (unused)
5959
m := newMockB()
60-
go bs.handleBroadcast(m)
60+
b := newBroadcaster(bs)
61+
go b.queueBroadcastMessages(m)
6162
defer close(m.recvChan)
6263

64+
bs.halt()
65+
6366
for i := 0; i < 2; i++ {
6467
m.recvChan <- &ab.BroadcastMessage{[]byte("Some bytes")}
6568
reply := <-m.sendChan
@@ -73,6 +76,37 @@ func TestQueueOverflow(t *testing.T) {
7376
if reply.Status != ab.Status_SERVICE_UNAVAILABLE {
7477
t.Fatalf("Should not have successfully queued the message")
7578
}
79+
80+
}
81+
82+
func TestMultiQueueOverflow(t *testing.T) {
83+
bs := newPlainBroadcastServer(2, 1, time.Second, nil) // queueSize, batchSize (unused), batchTimeout (unused), ramLedger (unused)
84+
// m := newMockB()
85+
ms := []*mockB{newMockB(), newMockB(), newMockB()}
86+
87+
for _, m := range ms {
88+
b := newBroadcaster(bs)
89+
go b.queueBroadcastMessages(m)
90+
defer close(m.recvChan)
91+
}
92+
93+
for _, m := range ms {
94+
for i := 0; i < 2; i++ {
95+
m.recvChan <- &ab.BroadcastMessage{[]byte("Some bytes")}
96+
reply := <-m.sendChan
97+
if reply.Status != ab.Status_SUCCESS {
98+
t.Fatalf("Should have successfully queued the message")
99+
}
100+
}
101+
}
102+
103+
for _, m := range ms {
104+
m.recvChan <- &ab.BroadcastMessage{[]byte("Some bytes")}
105+
reply := <-m.sendChan
106+
if reply.Status != ab.Status_SERVICE_UNAVAILABLE {
107+
t.Fatalf("Should not have successfully queued the message")
108+
}
109+
}
76110
}
77111

78112
func TestEmptyBroadcastMessage(t *testing.T) {
@@ -103,7 +137,7 @@ func TestFilledBatch(t *testing.T) {
103137
defer bs.halt()
104138
messages := 11 // Sending 11 messages, with a batch size of 2, ensures the 10th message is processed before we proceed for 5 blocks
105139
for i := 0; i < messages; i++ {
106-
bs.queue <- &ab.BroadcastMessage{[]byte("Some bytes")}
140+
bs.sendChan <- &ab.BroadcastMessage{[]byte("Some bytes")}
107141
}
108142
expected := uint64(1 + messages/batchSize)
109143
if bs.rl.(rawledger.Reader).Height() != expected {

0 commit comments

Comments
 (0)