1
1
use std:: sync:: atomic:: { AtomicBool , Ordering } ;
2
2
use std:: vec;
3
3
use std:: {
4
- collections:: { hash_map :: Entry , HashMap } ,
5
- sync:: Mutex ,
4
+ collections:: HashMap ,
5
+ sync:: { Mutex , RwLock } ,
6
6
time:: SystemTime ,
7
7
} ;
8
8
@@ -18,7 +18,7 @@ use super::{
18
18
19
19
/// The storage for sums.
20
20
struct ValueMap < T : Number < T > > {
21
- values : Mutex < HashMap < AttributeSet , T > > ,
21
+ values : RwLock < HashMap < AttributeSet , T :: AtomicTracker > > ,
22
22
has_no_value_attribute_value : AtomicBool ,
23
23
no_attribute_value : T :: AtomicTracker ,
24
24
}
@@ -32,7 +32,7 @@ impl<T: Number<T>> Default for ValueMap<T> {
32
32
impl < T : Number < T > > ValueMap < T > {
33
33
fn new ( ) -> Self {
34
34
ValueMap {
35
- values : Mutex :: new ( HashMap :: new ( ) ) ,
35
+ values : RwLock :: new ( HashMap :: new ( ) ) ,
36
36
has_no_value_attribute_value : AtomicBool :: new ( false ) ,
37
37
no_attribute_value : T :: new_atomic_tracker ( ) ,
38
38
}
@@ -45,21 +45,31 @@ impl<T: Number<T>> ValueMap<T> {
45
45
self . no_attribute_value . add ( measurement) ;
46
46
self . has_no_value_attribute_value
47
47
. store ( true , Ordering :: Release ) ;
48
- } else if let Ok ( mut values) = self . values . lock ( ) {
49
- let size = values. len ( ) ;
50
- match values. entry ( attrs) {
51
- Entry :: Occupied ( mut occupied_entry) => {
52
- let sum = occupied_entry. get_mut ( ) ;
53
- * sum += measurement;
54
- }
55
- Entry :: Vacant ( vacant_entry) => {
56
- if is_under_cardinality_limit ( size) {
57
- vacant_entry. insert ( measurement) ;
58
- } else if let Some ( val) = values. get_mut ( & STREAM_OVERFLOW_ATTRIBUTE_SET ) {
59
- * val += measurement;
48
+ } else if let Ok ( values) = self . values . read ( ) {
49
+ if let Some ( value_to_update) = values. get ( & attrs) {
50
+ value_to_update. add ( measurement) ;
51
+ return ;
52
+ } else {
53
+ drop ( values) ;
54
+ if let Ok ( mut values) = self . values . write ( ) {
55
+ // Recheck after acquiring write lock, in case another
56
+ // thread has added the value.
57
+ if let Some ( value_to_update) = values. get ( & attrs) {
58
+ value_to_update. add ( measurement) ;
59
+ return ;
60
+ } else if is_under_cardinality_limit ( values. len ( ) ) {
61
+ let new_value = T :: new_atomic_tracker ( ) ;
62
+ new_value. add ( measurement) ;
63
+ values. insert ( attrs, new_value) ;
64
+ } else if let Some ( overflow_value) =
65
+ values. get_mut ( & STREAM_OVERFLOW_ATTRIBUTE_SET )
66
+ {
67
+ overflow_value. add ( measurement) ;
60
68
return ;
61
69
} else {
62
- values. insert ( STREAM_OVERFLOW_ATTRIBUTE_SET . clone ( ) , measurement) ;
70
+ let new_value = T :: new_atomic_tracker ( ) ;
71
+ new_value. add ( measurement) ;
72
+ values. insert ( STREAM_OVERFLOW_ATTRIBUTE_SET . clone ( ) , new_value) ;
63
73
global:: handle_error ( MetricsError :: Other ( "Warning: Maximum data points for metric stream exceeded. Entry added to overflow. Subsequent overflows to same metric until next collect will not be logged." . into ( ) ) ) ;
64
74
}
65
75
}
@@ -114,7 +124,7 @@ impl<T: Number<T>> Sum<T> {
114
124
s_data. is_monotonic = self . monotonic ;
115
125
s_data. data_points . clear ( ) ;
116
126
117
- let mut values = match self . value_map . values . lock ( ) {
127
+ let mut values = match self . value_map . values . write ( ) {
118
128
Ok ( v) => v,
119
129
Err ( _) => return ( 0 , None ) ,
120
130
} ;
@@ -149,7 +159,7 @@ impl<T: Number<T>> Sum<T> {
149
159
. collect ( ) ,
150
160
start_time : Some ( prev_start) ,
151
161
time : Some ( t) ,
152
- value,
162
+ value : value . get_value ( ) ,
153
163
exemplars : vec ! [ ] ,
154
164
} ) ;
155
165
}
@@ -186,7 +196,7 @@ impl<T: Number<T>> Sum<T> {
186
196
s_data. is_monotonic = self . monotonic ;
187
197
s_data. data_points . clear ( ) ;
188
198
189
- let values = match self . value_map . values . lock ( ) {
199
+ let values = match self . value_map . values . write ( ) {
190
200
Ok ( v) => v,
191
201
Err ( _) => return ( 0 , None ) ,
192
202
} ;
@@ -226,7 +236,7 @@ impl<T: Number<T>> Sum<T> {
226
236
. collect ( ) ,
227
237
start_time : Some ( prev_start) ,
228
238
time : Some ( t) ,
229
- value : * value,
239
+ value : value. get_value ( ) ,
230
240
exemplars : vec ! [ ] ,
231
241
} ) ;
232
242
}
@@ -282,7 +292,7 @@ impl<T: Number<T>> PrecomputedSum<T> {
282
292
s_data. temporality = Temporality :: Delta ;
283
293
s_data. is_monotonic = self . monotonic ;
284
294
285
- let mut values = match self . value_map . values . lock ( ) {
295
+ let mut values = match self . value_map . values . write ( ) {
286
296
Ok ( v) => v,
287
297
Err ( _) => return ( 0 , None ) ,
288
298
} ;
@@ -315,9 +325,9 @@ impl<T: Number<T>> PrecomputedSum<T> {
315
325
316
326
let default = T :: default ( ) ;
317
327
for ( attrs, value) in values. drain ( ) {
318
- let delta = value - * reported. get ( & attrs) . unwrap_or ( & default) ;
328
+ let delta = value. get_value ( ) - * reported. get ( & attrs) . unwrap_or ( & default) ;
319
329
if delta != default {
320
- new_reported. insert ( attrs. clone ( ) , value) ;
330
+ new_reported. insert ( attrs. clone ( ) , value. get_value ( ) ) ;
321
331
}
322
332
s_data. data_points . push ( DataPoint {
323
333
attributes : attrs
@@ -367,7 +377,7 @@ impl<T: Number<T>> PrecomputedSum<T> {
367
377
s_data. temporality = Temporality :: Cumulative ;
368
378
s_data. is_monotonic = self . monotonic ;
369
379
370
- let values = match self . value_map . values . lock ( ) {
380
+ let values = match self . value_map . values . write ( ) {
371
381
Ok ( v) => v,
372
382
Err ( _) => return ( 0 , None ) ,
373
383
} ;
@@ -400,9 +410,9 @@ impl<T: Number<T>> PrecomputedSum<T> {
400
410
401
411
let default = T :: default ( ) ;
402
412
for ( attrs, value) in values. iter ( ) {
403
- let delta = * value - * reported. get ( attrs) . unwrap_or ( & default) ;
413
+ let delta = value. get_value ( ) - * reported. get ( attrs) . unwrap_or ( & default) ;
404
414
if delta != default {
405
- new_reported. insert ( attrs. clone ( ) , * value) ;
415
+ new_reported. insert ( attrs. clone ( ) , value. get_value ( ) ) ;
406
416
}
407
417
s_data. data_points . push ( DataPoint {
408
418
attributes : attrs
0 commit comments