You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
3.5 KiB

  1. package pubsub
  2. import (
  3. abci "github.com/tendermint/tendermint/abci/types"
  4. "github.com/tendermint/tendermint/internal/pubsub/query"
  5. "github.com/tendermint/tendermint/types"
  6. )
  7. // An item to be published to subscribers.
  8. type item struct {
  9. Data types.EventData
  10. Events []abci.Event
  11. }
  12. // A subInfo value records a single subscription.
  13. type subInfo struct {
  14. clientID string // chosen by the client
  15. query *query.Query // chosen by the client
  16. subID string // assigned at registration
  17. sub *Subscription // receives published events
  18. }
  19. // A subInfoSet is an unordered set of subscription info records.
  20. type subInfoSet map[*subInfo]struct{}
  21. func (s subInfoSet) contains(si *subInfo) bool { _, ok := s[si]; return ok }
  22. func (s subInfoSet) add(si *subInfo) { s[si] = struct{}{} }
  23. func (s subInfoSet) remove(si *subInfo) { delete(s, si) }
  24. // withQuery returns the subset of s whose query string matches qs.
  25. func (s subInfoSet) withQuery(qs string) subInfoSet {
  26. out := make(subInfoSet)
  27. for si := range s {
  28. if si.query.String() == qs {
  29. out.add(si)
  30. }
  31. }
  32. return out
  33. }
  34. // A subIndex is an indexed collection of subscription info records.
  35. // The index is not safe for concurrent use without external synchronization.
  36. type subIndex struct {
  37. all subInfoSet // all subscriptions
  38. byClient map[string]subInfoSet // per-client subscriptions
  39. byQuery map[string]subInfoSet // per-query subscriptions
  40. // TODO(creachadair): We allow indexing by query to support existing use by
  41. // the RPC service methods for event streaming. Fix up those methods not to
  42. // require this, and then remove indexing by query.
  43. }
  44. // newSubIndex constructs a new, empty subscription index.
  45. func newSubIndex() *subIndex {
  46. return &subIndex{
  47. all: make(subInfoSet),
  48. byClient: make(map[string]subInfoSet),
  49. byQuery: make(map[string]subInfoSet),
  50. }
  51. }
  52. // findClients returns the set of subscriptions for the given client ID, or nil.
  53. func (idx *subIndex) findClientID(id string) subInfoSet { return idx.byClient[id] }
  54. // findQuery returns the set of subscriptions on the given query string, or nil.
  55. func (idx *subIndex) findQuery(qs string) subInfoSet { return idx.byQuery[qs] }
  56. // contains reports whether idx contains any subscription matching the given
  57. // client ID and query pair.
  58. func (idx *subIndex) contains(clientID, query string) bool {
  59. csubs, qsubs := idx.byClient[clientID], idx.byQuery[query]
  60. if len(csubs) == 0 || len(qsubs) == 0 {
  61. return false
  62. }
  63. for si := range csubs {
  64. if qsubs.contains(si) {
  65. return true
  66. }
  67. }
  68. return false
  69. }
  70. // add adds si to the index, replacing any previous entry with the same terms.
  71. // It is the caller's responsibility to check for duplicates before adding.
  72. // See also the contains method.
  73. func (idx *subIndex) add(si *subInfo) {
  74. idx.all.add(si)
  75. if m := idx.byClient[si.clientID]; m == nil {
  76. idx.byClient[si.clientID] = subInfoSet{si: struct{}{}}
  77. } else {
  78. m.add(si)
  79. }
  80. qs := si.query.String()
  81. if m := idx.byQuery[qs]; m == nil {
  82. idx.byQuery[qs] = subInfoSet{si: struct{}{}}
  83. } else {
  84. m.add(si)
  85. }
  86. }
  87. // removeAll removes all the elements of s from the index.
  88. func (idx *subIndex) removeAll(s subInfoSet) {
  89. for si := range s {
  90. idx.all.remove(si)
  91. idx.byClient[si.clientID].remove(si)
  92. if len(idx.byClient[si.clientID]) == 0 {
  93. delete(idx.byClient, si.clientID)
  94. }
  95. if si.query != nil {
  96. qs := si.query.String()
  97. idx.byQuery[qs].remove(si)
  98. if len(idx.byQuery[qs]) == 0 {
  99. delete(idx.byQuery, qs)
  100. }
  101. }
  102. }
  103. }