Skip to content

Commit 2a49a4d

Browse files
authored
OCPBUGS-5523: Catalog, fatal error: concurrent map read and map write (#2913)
* protected subscriptionSyncCounters access to prevent concurrent map writes Signed-off-by: Daniel Franz <[email protected]> * organize map and mutex into single struct Signed-off-by: Daniel Franz <[email protected]> * initialize struct Signed-off-by: Daniel Franz <[email protected]> * use RWMutex to allow concurrent reads Signed-off-by: Daniel Franz <[email protected]> Signed-off-by: Daniel Franz <[email protected]>
1 parent 6c564a6 commit 2a49a4d

File tree

1 file changed

+36
-9
lines changed

1 file changed

+36
-9
lines changed

pkg/metrics/metrics.go

+36-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package metrics
22

33
import (
4+
"sync"
45
"time"
56

67
"github.com/prometheus/client_golang/prometheus"
@@ -199,12 +200,37 @@ var (
199200
},
200201
)
201202

202-
// subscriptionSyncCounters keeps a record of the Prometheus counters emitted by
203-
// Subscription objects. The key of a record is the Subscription name, while the value
204-
// is struct containing label values used in the counter
205-
subscriptionSyncCounters = make(map[string]subscriptionSyncLabelValues)
203+
subscriptionSyncCounters = newSubscriptionSyncCounter()
206204
)
207205

206+
// subscriptionSyncCounter keeps a record of the Prometheus counters emitted by
207+
// Subscription objects. The key of a record is the Subscription name, while the value
208+
// is struct containing label values used in the counter. Read and Write access are
209+
// protected by mutex.
210+
type subscriptionSyncCounter struct {
211+
counters map[string]subscriptionSyncLabelValues
212+
countersLock sync.RWMutex
213+
}
214+
215+
func newSubscriptionSyncCounter() subscriptionSyncCounter {
216+
return subscriptionSyncCounter{
217+
counters: make(map[string]subscriptionSyncLabelValues),
218+
}
219+
}
220+
221+
func (s *subscriptionSyncCounter) setValues(key string, val subscriptionSyncLabelValues) {
222+
s.countersLock.Lock()
223+
defer s.countersLock.Unlock()
224+
s.counters[key] = val
225+
}
226+
227+
func (s *subscriptionSyncCounter) readValues(key string) (subscriptionSyncLabelValues, bool) {
228+
s.countersLock.RLock()
229+
defer s.countersLock.RUnlock()
230+
val, ok := s.counters[key]
231+
return val, ok
232+
}
233+
208234
type subscriptionSyncLabelValues struct {
209235
installedCSV string
210236
pkg string
@@ -280,14 +306,15 @@ func EmitSubMetric(sub *operatorsv1alpha1.Subscription) {
280306
if sub.Spec == nil {
281307
return
282308
}
309+
283310
SubscriptionSyncCount.WithLabelValues(sub.GetName(), sub.Status.InstalledCSV, sub.Spec.Channel, sub.Spec.Package, string(sub.Spec.InstallPlanApproval)).Inc()
284-
if _, present := subscriptionSyncCounters[sub.GetName()]; !present {
285-
subscriptionSyncCounters[sub.GetName()] = subscriptionSyncLabelValues{
311+
if _, present := subscriptionSyncCounters.readValues(sub.GetName()); !present {
312+
subscriptionSyncCounters.setValues(sub.GetName(), subscriptionSyncLabelValues{
286313
installedCSV: sub.Status.InstalledCSV,
287314
pkg: sub.Spec.Package,
288315
channel: sub.Spec.Channel,
289316
approvalStrategy: string(sub.Spec.InstallPlanApproval),
290-
}
317+
})
291318
}
292319
}
293320

@@ -302,7 +329,7 @@ func UpdateSubsSyncCounterStorage(sub *operatorsv1alpha1.Subscription) {
302329
if sub.Spec == nil {
303330
return
304331
}
305-
counterValues := subscriptionSyncCounters[sub.GetName()]
332+
counterValues, _ := subscriptionSyncCounters.readValues(sub.GetName())
306333
approvalStrategy := string(sub.Spec.InstallPlanApproval)
307334

308335
if sub.Spec.Channel != counterValues.channel ||
@@ -317,7 +344,7 @@ func UpdateSubsSyncCounterStorage(sub *operatorsv1alpha1.Subscription) {
317344
counterValues.channel = sub.Spec.Channel
318345
counterValues.approvalStrategy = approvalStrategy
319346

320-
subscriptionSyncCounters[sub.GetName()] = counterValues
347+
subscriptionSyncCounters.setValues(sub.GetName(), counterValues)
321348
}
322349
}
323350

0 commit comments

Comments
 (0)