1414 * limitations under the License.
1515 */
1616
17+ use std:: collections:: HashMap ;
1718use std:: sync:: {
1819 atomic:: { AtomicU64 , Ordering } ,
19- Arc ,
20+ Arc , Mutex ,
2021} ;
2122
2223use public:: proto:: agent:: Exception ;
2324
2425#[ derive( Clone , Debug , Default ) ]
25- pub struct ExceptionHandler ( Arc < AtomicU64 > ) ;
26+ pub struct ExceptionHandler {
27+ exception : Arc < AtomicU64 > ,
28+ descriptions : Arc < Mutex < HashMap < u64 , String > > > ,
29+ }
2630
2731impl ExceptionHandler {
2832 const AUTO_CLEAR_BITS : u64 = Exception :: NpbNoGwArp as u64
@@ -38,21 +42,52 @@ impl ExceptionHandler {
3842 | Exception :: NpbSocketError as u64
3943 | Exception :: DataBpsThresholdExceeded as u64 ;
4044
41- pub fn set ( & self , e : Exception ) {
42- self . 0 . fetch_or ( e as u64 , Ordering :: SeqCst ) ;
45+ pub fn set ( & self , e : Exception , description : Option < String > ) {
46+ self . exception . fetch_or ( e as u64 , Ordering :: SeqCst ) ;
47+ if let Some ( d) = description {
48+ self . descriptions . lock ( ) . unwrap ( ) . insert ( e as u64 , d) ;
49+ }
4350 }
4451
4552 pub fn has ( & self , e : Exception ) -> bool {
4653 let e = e as u64 ;
47- self . 0 . load ( Ordering :: Relaxed ) & e == e
54+ self . exception . load ( Ordering :: Relaxed ) & e == e
4855 }
4956
5057 pub fn clear ( & self , e : Exception ) {
51- self . 0 . fetch_and ( !( e as u64 ) , Ordering :: SeqCst ) ;
58+ self . exception . fetch_and ( !( e as u64 ) , Ordering :: SeqCst ) ;
59+ self . descriptions . lock ( ) . unwrap ( ) . remove ( & ( e as u64 ) ) ;
5260 }
5361
54- pub fn take ( & self ) -> u64 {
55- self . 0 . fetch_and ( !Self :: AUTO_CLEAR_BITS , Ordering :: SeqCst )
62+ pub fn take ( & self ) -> ( u64 , Option < String > ) {
63+ let bits = self
64+ . exception
65+ . fetch_and ( !Self :: AUTO_CLEAR_BITS , Ordering :: SeqCst ) ;
66+ let mut descriptions = self . descriptions . lock ( ) . unwrap ( ) ;
67+ let mut result = vec ! [ ] ;
68+ for i in 0 ..64 {
69+ let bit = 1u64 << i;
70+ if bits & bit == bit {
71+ let mut description = if bit & Self :: AUTO_CLEAR_BITS == bit {
72+ descriptions. remove ( & bit)
73+ } else {
74+ descriptions. get ( & bit) . cloned ( )
75+ } ;
76+
77+ if let Some ( d) = description. take ( ) {
78+ result. push ( d) ;
79+ }
80+ }
81+ }
82+
83+ (
84+ bits,
85+ if result. is_empty ( ) {
86+ None
87+ } else {
88+ Some ( result. join ( ";" ) )
89+ } ,
90+ )
5691 }
5792}
5893
@@ -65,9 +100,9 @@ mod tests {
65100 let mut expected = 0u64 ;
66101 let h = ExceptionHandler :: default ( ) ;
67102
68- h. set ( Exception :: DiskNotEnough ) ;
103+ h. set ( Exception :: DiskNotEnough , None ) ;
69104 expected |= Exception :: DiskNotEnough as u64 ;
70- assert_eq ! ( h. take( ) , expected) ;
105+ assert_eq ! ( h. take( ) . 0 , expected) ;
71106
72107 let exceptions = vec ! [
73108 Exception :: DiskNotEnough ,
@@ -79,17 +114,39 @@ mod tests {
79114 ] ;
80115 expected = 0 ;
81116 for e in exceptions {
82- h. set ( e) ;
117+ h. set ( e, None ) ;
83118 expected |= e as u64 ;
84- assert_eq ! ( h. 0 . load( Ordering :: Relaxed ) , expected) ;
119+ assert_eq ! ( h. exception . load( Ordering :: Relaxed ) , expected) ;
85120 }
86121
87122 h. clear ( Exception :: DiskNotEnough ) ;
88123 expected &= !( Exception :: DiskNotEnough as u64 ) ;
89- assert_eq ! ( h. 0 . load( Ordering :: Relaxed ) , expected) ;
124+ assert_eq ! ( h. exception . load( Ordering :: Relaxed ) , expected) ;
90125
91- assert_eq ! ( h. take( ) , expected) ;
126+ assert_eq ! ( h. take( ) . 0 , expected) ;
92127 expected &= !( ExceptionHandler :: AUTO_CLEAR_BITS ) ;
93- assert_eq ! ( h. 0 . load( Ordering :: Relaxed ) , expected) ;
128+ assert_eq ! ( h. exception. load( Ordering :: Relaxed ) , expected) ;
129+
130+ let h = ExceptionHandler :: default ( ) ;
131+ h. set (
132+ Exception :: ControllerSocketError ,
133+ Some ( "controller socket error" . to_string ( ) ) ,
134+ ) ;
135+ h. set (
136+ Exception :: MemNotEnough ,
137+ Some ( "memory not enough" . to_string ( ) ) ,
138+ ) ;
139+ let ( bits, descriptions) = h. take ( ) ;
140+ assert_eq ! (
141+ bits,
142+ ( Exception :: ControllerSocketError as u64 ) | ( Exception :: MemNotEnough as u64 )
143+ ) ;
144+ assert_eq ! (
145+ descriptions,
146+ Some ( "memory not enough;controller socket error" . to_string( ) )
147+ ) ;
148+ let ( bits, descriptions) = h. take ( ) ;
149+ assert_eq ! ( bits, Exception :: MemNotEnough as u64 ) ;
150+ assert_eq ! ( descriptions, Some ( "memory not enough" . to_string( ) ) ) ;
94151 }
95152}
0 commit comments