mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-05 09:31:20 +00:00
get rid of clientToQueryMap
This commit is contained in:
parent
7268ec8d10
commit
c6e7015245
@ -247,9 +247,7 @@ func (s *Server) OnStop() {
|
|||||||
// NOTE: not goroutine safe
|
// NOTE: not goroutine safe
|
||||||
type state struct {
|
type state struct {
|
||||||
// query string -> client -> subscription
|
// query string -> client -> subscription
|
||||||
queryToSubscriptionMap map[string]map[string]*Subscription
|
subscriptions map[string]map[string]*Subscription
|
||||||
// client -> query string -> struct{}
|
|
||||||
clientToQueryMap map[string]map[string]struct{}
|
|
||||||
// query string -> queryPlusRefCount
|
// query string -> queryPlusRefCount
|
||||||
queries map[string]*queryPlusRefCount
|
queries map[string]*queryPlusRefCount
|
||||||
}
|
}
|
||||||
@ -264,8 +262,7 @@ type queryPlusRefCount struct {
|
|||||||
// OnStart implements Service.OnStart by starting the server.
|
// OnStart implements Service.OnStart by starting the server.
|
||||||
func (s *Server) OnStart() error {
|
func (s *Server) OnStart() error {
|
||||||
go s.loop(state{
|
go s.loop(state{
|
||||||
queryToSubscriptionMap: make(map[string]map[string]*Subscription),
|
subscriptions: make(map[string]map[string]*Subscription),
|
||||||
clientToQueryMap: make(map[string]map[string]struct{}),
|
|
||||||
queries: make(map[string]*queryPlusRefCount),
|
queries: make(map[string]*queryPlusRefCount),
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
@ -282,14 +279,12 @@ loop:
|
|||||||
switch cmd.op {
|
switch cmd.op {
|
||||||
case unsub:
|
case unsub:
|
||||||
if cmd.query != nil {
|
if cmd.query != nil {
|
||||||
state.remove(cmd.clientID, cmd.query, ErrUnsubscribed)
|
state.remove(cmd.clientID, cmd.query.String(), ErrUnsubscribed)
|
||||||
} else {
|
} else {
|
||||||
state.removeAll(cmd.clientID, ErrUnsubscribed)
|
state.removeClient(cmd.clientID, ErrUnsubscribed)
|
||||||
}
|
}
|
||||||
case shutdown:
|
case shutdown:
|
||||||
for clientID := range state.clientToQueryMap {
|
state.removeAll(nil)
|
||||||
state.removeAll(clientID, nil)
|
|
||||||
}
|
|
||||||
break loop
|
break loop
|
||||||
case sub:
|
case sub:
|
||||||
state.add(cmd.clientID, cmd.query, cmd.subscription)
|
state.add(cmd.clientID, cmd.query, cmd.subscription)
|
||||||
@ -302,36 +297,28 @@ loop:
|
|||||||
func (state *state) add(clientID string, q Query, subscription *Subscription) {
|
func (state *state) add(clientID string, q Query, subscription *Subscription) {
|
||||||
qStr := q.String()
|
qStr := q.String()
|
||||||
|
|
||||||
// initialize clientToSubscriptionMap per query if needed
|
// initialize subscription for this client per query if needed
|
||||||
if _, ok := state.queryToSubscriptionMap[qStr]; !ok {
|
if _, ok := state.subscriptions[qStr]; !ok {
|
||||||
state.queryToSubscriptionMap[qStr] = make(map[string]*Subscription)
|
state.subscriptions[qStr] = make(map[string]*Subscription)
|
||||||
}
|
}
|
||||||
// create subscription
|
// create subscription
|
||||||
state.queryToSubscriptionMap[qStr][clientID] = subscription
|
state.subscriptions[qStr][clientID] = subscription
|
||||||
|
|
||||||
// initialize queries if needed
|
// initialize query if needed
|
||||||
if _, ok := state.queries[qStr]; !ok {
|
if _, ok := state.queries[qStr]; !ok {
|
||||||
state.queries[qStr] = &queryPlusRefCount{q: q, refCount: 0}
|
state.queries[qStr] = &queryPlusRefCount{q: q, refCount: 0}
|
||||||
}
|
}
|
||||||
// increment reference counter
|
// increment reference counter
|
||||||
state.queries[qStr].refCount++
|
state.queries[qStr].refCount++
|
||||||
|
|
||||||
// add client if needed
|
|
||||||
if _, ok := state.clientToQueryMap[clientID]; !ok {
|
|
||||||
state.clientToQueryMap[clientID] = make(map[string]struct{})
|
|
||||||
}
|
|
||||||
state.clientToQueryMap[clientID][qStr] = struct{}{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *state) remove(clientID string, q Query, reason error) {
|
func (state *state) remove(clientID string, qStr string, reason error) {
|
||||||
qStr := q.String()
|
clientSubscriptions, ok := state.subscriptions[qStr]
|
||||||
|
|
||||||
clientToSubscriptionMap, ok := state.queryToSubscriptionMap[qStr]
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
subscription, ok := clientToSubscriptionMap[clientID]
|
subscription, ok := clientSubscriptions[clientID]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -341,18 +328,11 @@ func (state *state) remove(clientID string, q Query, reason error) {
|
|||||||
subscription.mtx.Unlock()
|
subscription.mtx.Unlock()
|
||||||
close(subscription.cancelled)
|
close(subscription.cancelled)
|
||||||
|
|
||||||
// remove the query from client map.
|
// remove client from query map.
|
||||||
// if client is not subscribed to anything else, remove it.
|
|
||||||
delete(state.clientToQueryMap[clientID], qStr)
|
|
||||||
if len(state.clientToQueryMap[clientID]) == 0 {
|
|
||||||
delete(state.clientToQueryMap, clientID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove the client from query map.
|
|
||||||
// if query has no other clients subscribed, remove it.
|
// if query has no other clients subscribed, remove it.
|
||||||
delete(state.queryToSubscriptionMap[qStr], clientID)
|
delete(state.subscriptions[qStr], clientID)
|
||||||
if len(state.queryToSubscriptionMap[qStr]) == 0 {
|
if len(state.subscriptions[qStr]) == 0 {
|
||||||
delete(state.queryToSubscriptionMap, qStr)
|
delete(state.subscriptions, qStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// decrease ref counter in queries
|
// decrease ref counter in queries
|
||||||
@ -363,43 +343,27 @@ func (state *state) remove(clientID string, q Query, reason error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *state) removeAll(clientID string, reason error) {
|
func (state *state) removeClient(clientID string, reason error) {
|
||||||
queryMap, ok := state.clientToQueryMap[clientID]
|
for qStr, clientSubscriptions := range state.subscriptions {
|
||||||
if !ok {
|
if _, ok := clientSubscriptions[clientID]; ok {
|
||||||
return
|
state.remove(clientID, qStr, reason)
|
||||||
}
|
|
||||||
|
|
||||||
for qStr := range queryMap {
|
|
||||||
subscription := state.queryToSubscriptionMap[qStr][clientID]
|
|
||||||
subscription.mtx.Lock()
|
|
||||||
subscription.err = reason
|
|
||||||
subscription.mtx.Unlock()
|
|
||||||
close(subscription.cancelled)
|
|
||||||
|
|
||||||
// remove the client from query map.
|
|
||||||
// if query has no other clients subscribed, remove it.
|
|
||||||
delete(state.queryToSubscriptionMap[qStr], clientID)
|
|
||||||
if len(state.queryToSubscriptionMap[qStr]) == 0 {
|
|
||||||
delete(state.queryToSubscriptionMap, qStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// decrease ref counter in queries
|
|
||||||
state.queries[qStr].refCount--
|
|
||||||
// remove the query if nobody else is using it
|
|
||||||
if state.queries[qStr].refCount == 0 {
|
|
||||||
delete(state.queries, qStr)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// remove the client.
|
func (state *state) removeAll(reason error) {
|
||||||
delete(state.clientToQueryMap, clientID)
|
for qStr, clientSubscriptions := range state.subscriptions {
|
||||||
|
for clientID := range clientSubscriptions {
|
||||||
|
state.remove(clientID, qStr, reason)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *state) send(msg interface{}, tags TagMap) {
|
func (state *state) send(msg interface{}, tags TagMap) {
|
||||||
for qStr, clientToSubscriptionMap := range state.queryToSubscriptionMap {
|
for qStr, clientSubscriptions := range state.subscriptions {
|
||||||
q := state.queries[qStr].q
|
q := state.queries[qStr].q
|
||||||
if q.Matches(tags) {
|
if q.Matches(tags) {
|
||||||
for clientID, subscription := range clientToSubscriptionMap {
|
for clientID, subscription := range clientSubscriptions {
|
||||||
if cap(subscription.out) == 0 {
|
if cap(subscription.out) == 0 {
|
||||||
// block on unbuffered channel
|
// block on unbuffered channel
|
||||||
subscription.out <- MsgAndTags{msg, tags}
|
subscription.out <- MsgAndTags{msg, tags}
|
||||||
@ -408,7 +372,7 @@ func (state *state) send(msg interface{}, tags TagMap) {
|
|||||||
select {
|
select {
|
||||||
case subscription.out <- MsgAndTags{msg, tags}:
|
case subscription.out <- MsgAndTags{msg, tags}:
|
||||||
default:
|
default:
|
||||||
state.remove(clientID, q, ErrOutOfCapacity)
|
state.remove(clientID, qStr, ErrOutOfCapacity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user