13
13
//
14
14
use std:: {
15
15
fmt:: DebugStruct ,
16
- sync:: { Arc , RwLock } ,
16
+ sync:: { Arc , RwLock , RwLockReadGuard , RwLockWriteGuard } ,
17
17
time:: Duration ,
18
18
} ;
19
19
20
+ use arc_swap:: ArcSwap ;
20
21
use async_trait:: async_trait;
21
22
use tokio:: sync:: { Mutex as AsyncMutex , MutexGuard as AsyncMutexGuard } ;
22
23
use zenoh_core:: { zasynclock, zcondfeat, zread, zwrite} ;
23
24
use zenoh_link:: Link ;
24
25
use zenoh_protocol:: {
25
- core:: { Priority , WhatAmI , ZenohIdProto } ,
26
+ core:: { Locator , Priority , Reliability , WhatAmI , ZenohIdProto } ,
26
27
network:: NetworkMessage ,
27
28
transport:: { close, Close , PrioritySn , TransportMessage , TransportSn } ,
28
29
} ;
@@ -31,7 +32,10 @@ use zenoh_result::{bail, zerror, ZResult};
31
32
#[ cfg( feature = "stats" ) ]
32
33
use crate :: stats:: TransportStats ;
33
34
use crate :: {
34
- common:: priority:: { TransportPriorityRx , TransportPriorityTx } ,
35
+ common:: {
36
+ pipeline:: TransmissionPipelineProducer ,
37
+ priority:: { TransportPriorityRx , TransportPriorityTx } ,
38
+ } ,
35
39
unicast:: {
36
40
authentication:: TransportAuthId ,
37
41
link:: { LinkUnicastWithOpenAck , TransportLinkUnicastDirection } ,
@@ -41,10 +45,54 @@ use crate::{
41
45
} ,
42
46
TransportManager , TransportPeerEventHandler ,
43
47
} ;
44
-
45
48
/*************************************/
46
49
/* UNIVERSAL TRANSPORT */
47
50
/*************************************/
51
+ /// Transport link storage with link selection caching functionality
52
+ #[ derive( Default ) ]
53
+ pub ( crate ) struct TransportLinks {
54
+ links : RwLock < Box < [ TransportLinkUnicastUniversal ] > > ,
55
+ cache : ArcSwap < [ [ Option < Arc < ScheduledLink > > ; Priority :: NUM ] ; 2 ] > ,
56
+ }
57
+
58
+ impl TransportLinks {
59
+ fn write ( & self ) -> RwLockWriteGuard < ' _ , Box < [ TransportLinkUnicastUniversal ] > > {
60
+ // on write access to the links we clear pipeline cache
61
+ self . cache . store ( Default :: default ( ) ) ;
62
+ zwrite ! ( self . links)
63
+ }
64
+
65
+ fn read ( & self ) -> RwLockReadGuard < ' _ , Box < [ TransportLinkUnicastUniversal ] > > {
66
+ zread ! ( self . links)
67
+ }
68
+
69
+ pub ( super ) fn get_link (
70
+ & self ,
71
+ reliability : Reliability ,
72
+ priority : Priority ,
73
+ select : impl FnOnce ( & [ TransportLinkUnicastUniversal ] ) -> Option < usize > ,
74
+ ) -> Option < Arc < ScheduledLink > > {
75
+ if let Some ( link) = self . cache . load ( ) [ reliability as usize ] [ priority as usize ] . clone ( ) {
76
+ return Some ( link) ;
77
+ }
78
+ let guard = self . read ( ) ;
79
+ let transport_link = & guard[ select ( & guard) ?] ;
80
+ let link = Arc :: new ( ScheduledLink {
81
+ pipeline : transport_link. pipeline . clone ( ) ,
82
+ dst : transport_link. link . link . get_dst ( ) . clone ( ) ,
83
+ } ) ;
84
+ let mut cache = self . cache . load ( ) . as_ref ( ) . clone ( ) ;
85
+ cache[ reliability as usize ] [ priority as usize ] = Some ( link. clone ( ) ) ;
86
+ self . cache . store ( Arc :: new ( cache) ) ;
87
+ Some ( link)
88
+ }
89
+ }
90
+
91
+ pub ( super ) struct ScheduledLink {
92
+ pub ( super ) pipeline : TransmissionPipelineProducer ,
93
+ pub ( super ) dst : Locator ,
94
+ }
95
+
48
96
#[ derive( Clone ) ]
49
97
pub ( crate ) struct TransportUnicastUniversal {
50
98
// Transport Manager
@@ -56,7 +104,7 @@ pub(crate) struct TransportUnicastUniversal {
56
104
// Rx priorities
57
105
pub ( super ) priority_rx : Arc < [ TransportPriorityRx ] > ,
58
106
// The links associated to the channel
59
- pub ( super ) links : Arc < RwLock < Box < [ TransportLinkUnicastUniversal ] > > > ,
107
+ pub ( super ) links : Arc < TransportLinks > ,
60
108
// The callback
61
109
pub ( super ) callback : Arc < RwLock < Option < Arc < dyn TransportPeerEventHandler > > > > ,
62
110
// Lock used to ensure no race in add_link method
@@ -104,7 +152,7 @@ impl TransportUnicastUniversal {
104
152
config,
105
153
priority_tx : priority_tx. into_boxed_slice ( ) . into ( ) ,
106
154
priority_rx : priority_rx. into_boxed_slice ( ) . into ( ) ,
107
- links : Arc :: new ( RwLock :: new ( vec ! [ ] . into_boxed_slice ( ) ) ) ,
155
+ links : Default :: default ( ) ,
108
156
add_link_lock : Arc :: new ( AsyncMutex :: new ( ( ) ) ) ,
109
157
callback : Arc :: new ( RwLock :: new ( None ) ) ,
110
158
alive : Arc :: new ( AsyncMutex :: new ( false ) ) ,
@@ -136,7 +184,7 @@ impl TransportUnicastUniversal {
136
184
137
185
// Close all the links
138
186
let mut links = {
139
- let mut l_guard = zwrite ! ( self . links) ;
187
+ let mut l_guard = self . links . write ( ) ;
140
188
let links = l_guard. to_vec ( ) ;
141
189
* l_guard = vec ! [ ] . into_boxed_slice ( ) ;
142
190
links
@@ -161,7 +209,7 @@ impl TransportUnicastUniversal {
161
209
162
210
// Try to remove the link
163
211
let target = {
164
- let mut guard = zwrite ! ( self . links) ;
212
+ let mut guard = self . links . write ( ) ;
165
213
166
214
if let Some ( index) = guard. iter ( ) . position ( |tl| {
167
215
// Compare LinkUnicast link to not compare TransportLinkUnicast direction
@@ -245,7 +293,7 @@ impl TransportUnicastTrait for TransportUnicastUniversal {
245
293
246
294
// Check if we can add more inbound links
247
295
{
248
- let guard = zread ! ( self . links) ;
296
+ let guard = self . links . read ( ) ;
249
297
if let TransportLinkUnicastDirection :: Inbound = link. inner_config ( ) . direction {
250
298
let count = guard
251
299
. iter ( )
@@ -283,7 +331,7 @@ impl TransportUnicastTrait for TransportUnicastUniversal {
283
331
TransportLinkUnicastUniversal :: new ( self , link, & self . priority_tx ) ;
284
332
285
333
// Add the link to the channel
286
- let mut guard = zwrite ! ( self . links) ;
334
+ let mut guard = self . links . write ( ) ;
287
335
let mut links = Vec :: with_capacity ( guard. len ( ) + 1 ) ;
288
336
links. extend_from_slice ( & guard) ;
289
337
links. push ( link. clone ( ) ) ;
@@ -357,7 +405,9 @@ impl TransportUnicastTrait for TransportUnicastUniversal {
357
405
async fn close ( & self , reason : u8 ) -> ZResult < ( ) > {
358
406
tracing:: trace!( "Closing transport with peer: {}" , self . config. zid) ;
359
407
360
- let mut pipelines = zread ! ( self . links)
408
+ let mut pipelines = self
409
+ . links
410
+ . read ( )
361
411
. iter ( )
362
412
. map ( |sl| sl. pipeline . clone ( ) )
363
413
. collect :: < Vec < _ > > ( ) ;
@@ -379,13 +429,14 @@ impl TransportUnicastTrait for TransportUnicastUniversal {
379
429
}
380
430
381
431
fn get_links ( & self ) -> Vec < Link > {
382
- zread ! ( self . links) . iter ( ) . map ( |l| l. link . link ( ) ) . collect ( )
432
+ self . links . read ( ) . iter ( ) . map ( |l| l. link . link ( ) ) . collect ( )
383
433
}
384
434
385
435
fn get_auth_ids ( & self ) -> TransportAuthId {
386
436
let mut transport_auth_id = TransportAuthId :: default ( ) ;
387
437
// Convert LinkUnicast auth ids to AuthId
388
- zread ! ( self . links)
438
+ self . links
439
+ . read ( )
389
440
. iter ( )
390
441
. for_each ( |l| transport_auth_id. push_link_auth_id ( l. link . link . get_auth_id ( ) . clone ( ) ) ) ;
391
442
0 commit comments