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 }