Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit 7cdef1d

Browse files
[FAB-6111]Use syncmap in eventhub
Change-Id: I3f3b2e58322d3c866cad04a904cf9e7ecdbac2de Signed-off-by: biljana lukovic <biljana.lukovic@securekey.com>
1 parent 308a18d commit 7cdef1d

File tree

3 files changed

+56
-60
lines changed

3 files changed

+56
-60
lines changed

Gopkg.lock

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/fabric-client/events/eventhub.go

Lines changed: 46 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,21 @@ import (
2727
pb "github.com/hyperledger/fabric/protos/peer"
2828
"github.com/hyperledger/fabric/protos/utils"
2929
"github.com/op/go-logging"
30+
syncmap "golang.org/x/sync/syncmap"
3031
)
3132

3233
var logger = logging.MustGetLogger("fabric_sdk_go")
3334

3435
// EventHub allows a client to listen to event at a peer.
3536
type EventHub struct {
36-
// Protects chaincodeRegistrants, blockRegistrants and txRegistrants
37+
//Used for protecting parts of code from running concurrently
3738
mtx sync.RWMutex
3839
// Map of clients registered for chaincode events
39-
chaincodeRegistrants map[string][]*fab.ChainCodeCBE
40-
// Map of clients registered for block events
40+
chaincodeRegistrants syncmap.Map
41+
// Array of clients registered for block events
4142
blockRegistrants []func(*common.Block)
4243
// Map of clients registered for transactional events
43-
txRegistrants map[string]func(string, pb.TxValidationCode, error)
44+
txRegistrants syncmap.Map
4445
// peer addr to connect to
4546
peerAddr string
4647
// peer tls certificate
@@ -77,21 +78,14 @@ func NewEventHub(client fab.FabricClient) (*EventHub, error) {
7778
if client == nil {
7879
return nil, fmt.Errorf("Client is nil")
7980
}
80-
chaincodeRegistrants := make(map[string][]*fab.ChainCodeCBE)
81-
txRegistrants := make(map[string]func(string, pb.TxValidationCode, error))
82-
8381
eventHub := EventHub{
84-
chaincodeRegistrants: chaincodeRegistrants,
85-
blockRegistrants: nil,
86-
txRegistrants: txRegistrants,
87-
interestedEvents: nil,
88-
eventsClientFactory: &consumerClientFactory{},
89-
client: client,
82+
blockRegistrants: nil,
83+
interestedEvents: nil,
84+
eventsClientFactory: &consumerClientFactory{},
85+
client: client,
9086
}
91-
9287
// register default transaction callback
9388
eventHub.RegisterBlockEvent(eventHub.txCallback)
94-
9589
return &eventHub, nil
9690
}
9791

@@ -328,15 +322,17 @@ func (eventHub *EventHub) RegisterChaincodeEvent(ccid string, eventname string,
328322
eventHub.addChaincodeInterest(ccid, eventname)
329323

330324
cbe := fab.ChainCodeCBE{CCID: ccid, EventNameFilter: eventname, CallbackFunc: callback}
331-
cbeArray := eventHub.chaincodeRegistrants[ccid]
332-
if cbeArray == nil && len(cbeArray) <= 0 {
325+
var cbeArray []*fab.ChainCodeCBE
326+
327+
ccRegistrantArray, ok := eventHub.chaincodeRegistrants.Load(ccid)
328+
if !ok {
333329
cbeArray = make([]*fab.ChainCodeCBE, 0)
334-
cbeArray = append(cbeArray, &cbe)
335-
eventHub.chaincodeRegistrants[ccid] = cbeArray
336330
} else {
337-
cbeArray = append(cbeArray, &cbe)
338-
eventHub.chaincodeRegistrants[ccid] = cbeArray
331+
cbeArray = ccRegistrantArray.([]*fab.ChainCodeCBE)
339332
}
333+
cbeArray = append(cbeArray, &cbe)
334+
eventHub.chaincodeRegistrants.Store(ccid, cbeArray)
335+
340336
return &cbe
341337
}
342338

@@ -348,21 +344,24 @@ func (eventHub *EventHub) UnregisterChaincodeEvent(cbe *fab.ChainCodeCBE) {
348344

349345
eventHub.removeChaincodeInterest(cbe.CCID, cbe.EventNameFilter)
350346

351-
cbeArray := eventHub.chaincodeRegistrants[cbe.CCID]
352-
if len(cbeArray) <= 0 {
353-
logger.Debugf("No event registration for ccid %s \n", cbe.CCID)
354-
return
355-
}
347+
ccRegistrantArray, ok := eventHub.chaincodeRegistrants.Load(cbe.CCID)
348+
if ok {
349+
cbeArray := ccRegistrantArray.([]*fab.ChainCodeCBE)
350+
if len(cbeArray) <= 0 {
351+
logger.Debugf("No event registration for ccid %s \n", cbe.CCID)
352+
return
353+
}
356354

357-
for i, v := range cbeArray {
358-
if v == cbe {
359-
newCbeArray := append(cbeArray[:i], cbeArray[i+1:]...)
360-
if len(newCbeArray) <= 0 {
361-
delete(eventHub.chaincodeRegistrants, cbe.CCID)
362-
} else {
363-
eventHub.chaincodeRegistrants[cbe.CCID] = newCbeArray
355+
for i, v := range cbeArray {
356+
if v == cbe {
357+
newCbeArray := append(cbeArray[:i], cbeArray[i+1:]...)
358+
if len(newCbeArray) <= 0 {
359+
eventHub.chaincodeRegistrants.Delete(cbe.CCID)
360+
} else {
361+
eventHub.chaincodeRegistrants.Store(cbe.CCID, newCbeArray)
362+
}
363+
break
364364
}
365-
break
366365
}
367366
}
368367
}
@@ -373,18 +372,14 @@ func (eventHub *EventHub) UnregisterChaincodeEvent(cbe *fab.ChainCodeCBE) {
373372
// is a json object representation of type "message Transaction"
374373
func (eventHub *EventHub) RegisterTxEvent(txnID apitxn.TransactionID, callback func(string, pb.TxValidationCode, error)) {
375374
logger.Debugf("reg txid %s\n", txnID.ID)
376-
377-
eventHub.mtx.Lock()
378-
eventHub.txRegistrants[txnID.ID] = callback
379-
eventHub.mtx.Unlock()
375+
eventHub.txRegistrants.Store(txnID.ID, callback)
380376
}
381377

382378
// UnregisterTxEvent unregister transactional event registration.
383379
// txid: transaction id
384380
func (eventHub *EventHub) UnregisterTxEvent(txnID apitxn.TransactionID) {
385-
eventHub.mtx.Lock()
386-
delete(eventHub.txRegistrants, txnID.ID)
387-
eventHub.mtx.Unlock()
381+
logger.Debugf("un-reg txid %s\n", txnID.ID)
382+
eventHub.txRegistrants.Delete(txnID.ID)
388383
}
389384

390385
/**
@@ -394,7 +389,6 @@ func (eventHub *EventHub) UnregisterTxEvent(txnID apitxn.TransactionID) {
394389
*/
395390
func (eventHub *EventHub) txCallback(block *common.Block) {
396391
logger.Debugf("txCallback block=%v\n", block)
397-
398392
txFilter := util.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
399393
for i, v := range block.Data.Data {
400394

@@ -416,7 +410,6 @@ func (eventHub *EventHub) txCallback(block *common.Block) {
416410
logger.Errorf("error extracting ChannelHeader from payload: %v\n", err)
417411
return
418412
}
419-
420413
callback := eventHub.getTXRegistrant(channelHeader.TxId)
421414
if callback != nil {
422415
if txFilter.IsInvalid(i) {
@@ -434,36 +427,33 @@ func (eventHub *EventHub) txCallback(block *common.Block) {
434427
func (eventHub *EventHub) getBlockRegistrants() []func(*common.Block) {
435428
eventHub.mtx.RLock()
436429
defer eventHub.mtx.RUnlock()
437-
438430
// Return a clone of the array to avoid race conditions
439431
clone := make([]func(*common.Block), len(eventHub.blockRegistrants))
440-
for i, registrant := range eventHub.blockRegistrants {
441-
clone[i] = registrant
442-
}
432+
copy(clone, eventHub.blockRegistrants)
443433
return clone
444434
}
445435

446436
func (eventHub *EventHub) getChaincodeRegistrants(chaincodeID string) []*fab.ChainCodeCBE {
447437
eventHub.mtx.RLock()
448438
defer eventHub.mtx.RUnlock()
449439

450-
registrants, ok := eventHub.chaincodeRegistrants[chaincodeID]
440+
registrants, ok := eventHub.chaincodeRegistrants.Load(chaincodeID)
451441
if !ok {
452442
return nil
453443
}
454-
444+
cbeRegistrants := registrants.([]*fab.ChainCodeCBE)
455445
// Return a clone of the array to avoid race conditions
456-
clone := make([]*fab.ChainCodeCBE, len(registrants))
457-
for i, registrants := range registrants {
458-
clone[i] = registrants
459-
}
446+
clone := make([]*fab.ChainCodeCBE, len(cbeRegistrants))
447+
copy(clone, cbeRegistrants)
460448
return clone
461449
}
462450

463451
func (eventHub *EventHub) getTXRegistrant(txID string) func(string, pb.TxValidationCode, error) {
464-
eventHub.mtx.RLock()
465-
defer eventHub.mtx.RUnlock()
466-
return eventHub.txRegistrants[txID]
452+
v, ok := eventHub.txRegistrants.Load(txID)
453+
if !ok {
454+
return nil
455+
}
456+
return v.(func(string, pb.TxValidationCode, error))
467457
}
468458

469459
// getChainCodeEvents parses block events for chaincode events associated with individual transactions

pkg/fabric-client/events/eventhub_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ func TestDeadlock(t *testing.T) {
4242
t.Fatalf("No client")
4343
}
4444

45-
threads := 20
46-
eventsPerThread := 100
45+
threads := 10
46+
eventsPerThread := 200
4747
eventsSent := eventsPerThread * threads
4848

4949
// The test should be done in milliseconds but if there's
5050
// a deadlock then we don't want it to hang
51-
timeout := 30 * time.Second
51+
timeout := 50 * time.Second
5252

5353
// create a flood of TX events
5454
txCompletion := newMultiCompletionHandler(eventsSent, timeout)

0 commit comments

Comments
 (0)