github.com/amazechain/amc@v0.1.3/internal/sync/subscription_topic_handler.go (about)

     1  package sync
     2  
     3  import (
     4  	"github.com/amazechain/amc/internal/p2p"
     5  	"github.com/amazechain/amc/log"
     6  	"sync"
     7  
     8  	pubsub "github.com/libp2p/go-libp2p-pubsub"
     9  )
    10  
    11  // This is a subscription topic handler that is used to handle basic
    12  // CRUD operations on the topic map. All operations are thread safe
    13  // so they can be called from multiple routines.
    14  type subTopicHandler struct {
    15  	sync.RWMutex
    16  	subTopics map[string]*pubsub.Subscription
    17  	digestMap map[[4]byte]int
    18  }
    19  
    20  func newSubTopicHandler() *subTopicHandler {
    21  	return &subTopicHandler{
    22  		subTopics: map[string]*pubsub.Subscription{},
    23  		digestMap: map[[4]byte]int{},
    24  	}
    25  }
    26  
    27  func (s *subTopicHandler) addTopic(topic string, sub *pubsub.Subscription) {
    28  	s.Lock()
    29  	defer s.Unlock()
    30  	s.subTopics[topic] = sub
    31  	digest, err := p2p.ExtractGossipDigest(topic)
    32  	if err != nil {
    33  		log.Error("Could not retrieve digest", "err", err)
    34  		return
    35  	}
    36  	s.digestMap[digest] += 1
    37  }
    38  
    39  func (s *subTopicHandler) topicExists(topic string) bool {
    40  	s.RLock()
    41  	defer s.RUnlock()
    42  	_, ok := s.subTopics[topic]
    43  	return ok
    44  }
    45  
    46  func (s *subTopicHandler) removeTopic(topic string) {
    47  	s.Lock()
    48  	defer s.Unlock()
    49  	delete(s.subTopics, topic)
    50  	digest, err := p2p.ExtractGossipDigest(topic)
    51  	if err != nil {
    52  		log.Error("Could not retrieve digest", "err", err)
    53  		return
    54  	}
    55  	currAmt, ok := s.digestMap[digest]
    56  	// Should never be possible, is a
    57  	// defensive check.
    58  	if !ok || currAmt <= 0 {
    59  		delete(s.digestMap, digest)
    60  		return
    61  	}
    62  	s.digestMap[digest] -= 1
    63  	if s.digestMap[digest] == 0 {
    64  		delete(s.digestMap, digest)
    65  	}
    66  }
    67  
    68  func (s *subTopicHandler) digestExists(digest [4]byte) bool {
    69  	s.RLock()
    70  	defer s.RUnlock()
    71  
    72  	count, ok := s.digestMap[digest]
    73  	return ok && count > 0
    74  }
    75  
    76  func (s *subTopicHandler) allTopics() []string {
    77  	s.RLock()
    78  	defer s.RUnlock()
    79  	var topics []string
    80  	for t := range s.subTopics {
    81  		copiedTopic := t
    82  		topics = append(topics, copiedTopic)
    83  	}
    84  	return topics
    85  }
    86  
    87  func (s *subTopicHandler) subForTopic(topic string) *pubsub.Subscription {
    88  	s.RLock()
    89  	defer s.RUnlock()
    90  	return s.subTopics[topic]
    91  }