Skip to content

Commit 0ab3fe3

Browse files
committed
nsqlookupd: fix write lock startvation
1 parent 5b67f58 commit 0ab3fe3

File tree

2 files changed

+45
-45
lines changed

2 files changed

+45
-45
lines changed

nsqlookupd/http.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,9 @@ func (s *httpServer) doDebug(w http.ResponseWriter, req *http.Request, ps httpro
308308
defer s.ctx.nsqlookupd.DB.RUnlock()
309309

310310
data := make(map[string][]map[string]interface{})
311-
for r, producers := range s.ctx.nsqlookupd.DB.registrationMap {
311+
s.ctx.nsqlookupd.DB.registrationMap.Range(func(k, v interface{}) bool {
312+
producers := v.(map[string]*Producer)
313+
r := k.(Registration)
312314
key := r.Category + ":" + r.Key + ":" + r.SubKey
313315
for _, p := range producers {
314316
m := map[string]interface{}{
@@ -324,7 +326,8 @@ func (s *httpServer) doDebug(w http.ResponseWriter, req *http.Request, ps httpro
324326
}
325327
data[key] = append(data[key], m)
326328
}
327-
}
329+
return true
330+
})
328331

329332
return data, nil
330333
}

nsqlookupd/registration_db.go

+40-43
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
type RegistrationDB struct {
1111
sync.RWMutex
12-
registrationMap map[Registration]ProducerMap
12+
registrationMap *sync.Map
1313
}
1414

1515
type Registration struct {
@@ -54,119 +54,116 @@ func (p *Producer) IsTombstoned(lifetime time.Duration) bool {
5454

5555
func NewRegistrationDB() *RegistrationDB {
5656
return &RegistrationDB{
57-
registrationMap: make(map[Registration]ProducerMap),
57+
registrationMap: &sync.Map{},
5858
}
5959
}
6060

6161
// add a registration key
6262
func (r *RegistrationDB) AddRegistration(k Registration) {
63-
r.Lock()
64-
defer r.Unlock()
65-
_, ok := r.registrationMap[k]
66-
if !ok {
67-
r.registrationMap[k] = make(map[string]*Producer)
68-
}
63+
r.registrationMap.LoadOrStore(k, make(map[string]*Producer))
6964
}
7065

7166
// add a producer to a registration
7267
func (r *RegistrationDB) AddProducer(k Registration, p *Producer) bool {
7368
r.Lock()
7469
defer r.Unlock()
75-
_, ok := r.registrationMap[k]
76-
if !ok {
77-
r.registrationMap[k] = make(map[string]*Producer)
78-
}
79-
producers := r.registrationMap[k]
70+
val, _ := r.registrationMap.LoadOrStore(k, make(map[string]*Producer))
71+
producers := val.(map[string]*Producer)
8072
_, found := producers[p.peerInfo.id]
8173
if found == false {
8274
producers[p.peerInfo.id] = p
8375
}
76+
77+
r.registrationMap.Store(k, producers)
8478
return !found
8579
}
8680

8781
// remove a producer from a registration
8882
func (r *RegistrationDB) RemoveProducer(k Registration, id string) (bool, int) {
8983
r.Lock()
9084
defer r.Unlock()
91-
producers, ok := r.registrationMap[k]
85+
value, ok := r.registrationMap.Load(k)
9286
if !ok {
9387
return false, 0
9488
}
89+
producers := value.(map[string]*Producer)
9590
removed := false
9691
if _, exists := producers[id]; exists {
9792
removed = true
9893
}
9994

10095
// Note: this leaves keys in the DB even if they have empty lists
10196
delete(producers, id)
97+
98+
r.registrationMap.Store(k, producers)
99+
102100
return removed, len(producers)
103101
}
104102

105103
// remove a Registration and all it's producers
106104
func (r *RegistrationDB) RemoveRegistration(k Registration) {
107-
r.Lock()
108-
defer r.Unlock()
109-
delete(r.registrationMap, k)
105+
r.registrationMap.Delete(k)
110106
}
111107

112108
func (r *RegistrationDB) needFilter(key string, subkey string) bool {
113109
return key == "*" || subkey == "*"
114110
}
115111

116112
func (r *RegistrationDB) FindRegistrations(category string, key string, subkey string) Registrations {
117-
r.RLock()
118-
defer r.RUnlock()
119113
if !r.needFilter(key, subkey) {
120114
k := Registration{category, key, subkey}
121-
if _, ok := r.registrationMap[k]; ok {
115+
if _, ok := r.registrationMap.Load(k); ok {
122116
return Registrations{k}
123117
}
124118
return Registrations{}
125119
}
126120
results := Registrations{}
127-
for k := range r.registrationMap {
128-
if !k.IsMatch(category, key, subkey) {
129-
continue
121+
r.registrationMap.Range(func(k, _ interface{}) bool {
122+
if k.(Registration).IsMatch(category, key, subkey) {
123+
results = append(results, k.(Registration))
130124
}
131-
results = append(results, k)
132-
}
125+
return true
126+
})
127+
133128
return results
134129
}
135130

136131
func (r *RegistrationDB) FindProducers(category string, key string, subkey string) Producers {
137-
r.RLock()
138-
defer r.RUnlock()
139132
if !r.needFilter(key, subkey) {
140133
k := Registration{category, key, subkey}
141-
return ProducerMap2Slice(r.registrationMap[k])
134+
val, _ := r.registrationMap.Load(k)
135+
return ProducerMap2Slice(val.(map[string]*Producer))
142136
}
143137

144138
results := make(map[string]struct{})
145139
var retProducers Producers
146-
for k, producers := range r.registrationMap {
147-
if !k.IsMatch(category, key, subkey) {
148-
continue
149-
}
150-
for _, producer := range producers {
151-
_, found := results[producer.peerInfo.id]
152-
if found == false {
153-
results[producer.peerInfo.id] = struct{}{}
154-
retProducers = append(retProducers, producer)
140+
r.registrationMap.Range(func(k, v interface{}) bool {
141+
if k.(Registration).IsMatch(category, key, subkey) {
142+
producers := v.(map[string]*Producer)
143+
for _, producer := range producers {
144+
_, found := results[producer.peerInfo.id]
145+
if found == false {
146+
results[producer.peerInfo.id] = struct{}{}
147+
retProducers = append(retProducers, producer)
148+
}
155149
}
156150
}
157-
}
151+
return true
152+
})
153+
158154
return retProducers
159155
}
160156

161157
func (r *RegistrationDB) LookupRegistrations(id string) Registrations {
162-
r.RLock()
163-
defer r.RUnlock()
164158
results := Registrations{}
165-
for k, producers := range r.registrationMap {
159+
r.registrationMap.Range(func(k, v interface{}) bool {
160+
producers := v.(map[string]*Producer)
166161
if _, exists := producers[id]; exists {
167-
results = append(results, k)
162+
results = append(results, k.(Registration))
168163
}
169-
}
164+
165+
return true
166+
})
170167
return results
171168
}
172169

0 commit comments

Comments
 (0)