33use std:: collections:: { HashMap , HashSet } ;
44use std:: net:: SocketAddr ;
55use std:: path:: PathBuf ;
6- use std:: sync:: atomic:: { AtomicBool , Ordering } ;
6+ use std:: sync:: atomic:: { AtomicBool , AtomicUsize , Ordering } ;
77use std:: sync:: Arc ;
88use std:: time:: { Duration , SystemTime } ;
99use tokio:: sync:: { mpsc, Mutex } ;
@@ -70,6 +70,8 @@ pub struct MultiPeerNetworkManager {
7070 user_agent : Option < String > ,
7171 /// Exclusive mode: restrict to configured peers only (no DNS or peer store)
7272 exclusive_mode : bool ,
73+ /// Cached count of currently connected peers for fast, non-blocking queries
74+ connected_peer_count : Arc < AtomicUsize > ,
7375}
7476
7577impl MultiPeerNetworkManager {
@@ -123,6 +125,7 @@ impl MultiPeerNetworkManager {
123125 peers_sent_headers2 : Arc :: new ( Mutex :: new ( HashSet :: new ( ) ) ) ,
124126 user_agent : config. user_agent . clone ( ) ,
125127 exclusive_mode,
128+ connected_peer_count : Arc :: new ( AtomicUsize :: new ( 0 ) ) ,
126129 } )
127130 }
128131
@@ -209,6 +212,7 @@ impl MultiPeerNetworkManager {
209212 let mempool_strategy = self . mempool_strategy ;
210213 let read_timeout = self . read_timeout ;
211214 let user_agent = self . user_agent . clone ( ) ;
215+ let connected_peer_count = self . connected_peer_count . clone ( ) ;
212216
213217 // Spawn connection task
214218 let mut tasks = self . tasks . lock ( ) . await ;
@@ -235,6 +239,9 @@ impl MultiPeerNetworkManager {
235239 return ;
236240 }
237241
242+ // Increment connected peer counter on successful add
243+ connected_peer_count. fetch_add ( 1 , Ordering :: Relaxed ) ;
244+
238245 // Add to known addresses
239246 addrv2_handler. add_known_address ( addr, ServiceFlags :: from ( 1 ) ) . await ;
240247
@@ -246,6 +253,7 @@ impl MultiPeerNetworkManager {
246253 addrv2_handler,
247254 shutdown,
248255 reputation_manager. clone ( ) ,
256+ connected_peer_count. clone ( ) ,
249257 )
250258 . await ;
251259 }
@@ -287,6 +295,7 @@ impl MultiPeerNetworkManager {
287295 addrv2_handler : Arc < AddrV2Handler > ,
288296 shutdown : Arc < AtomicBool > ,
289297 reputation_manager : Arc < PeerReputationManager > ,
298+ connected_peer_count : Arc < AtomicUsize > ,
290299 ) {
291300 tokio:: spawn ( async move {
292301 log:: debug!( "Starting peer reader loop for {}" , addr) ;
@@ -551,7 +560,11 @@ impl MultiPeerNetworkManager {
551560
552561 // Remove from pool
553562 log:: warn!( "Disconnecting from {} (peer reader loop ended)" , addr) ;
554- pool. remove_connection ( & addr) . await ;
563+ let removed = pool. remove_connection ( & addr) . await ;
564+ if removed. is_some ( ) {
565+ // Decrement connected peer counter when a connection is removed
566+ connected_peer_count. fetch_sub ( 1 , Ordering :: Relaxed ) ;
567+ }
555568
556569 // Give small positive reputation if peer maintained long connection
557570 let conn_duration = Duration :: from_secs ( 60 * loop_iteration) ; // Rough estimate
@@ -576,6 +589,7 @@ impl MultiPeerNetworkManager {
576589 let peer_search_started = self . peer_search_started . clone ( ) ;
577590 let initial_peers = self . initial_peers . clone ( ) ;
578591 let data_dir = self . data_dir . clone ( ) ;
592+ let connected_peer_count = self . connected_peer_count . clone ( ) ;
579593
580594 // Check if we're in exclusive mode (explicit flag or peers configured)
581595 let exclusive_mode = self . exclusive_mode ;
@@ -597,6 +611,8 @@ impl MultiPeerNetworkManager {
597611
598612 let count = pool. connection_count ( ) . await ;
599613 log:: debug!( "Connected peers: {}" , count) ;
614+ // Keep the cached counter in sync with actual pool count
615+ connected_peer_count. store ( count, Ordering :: Relaxed ) ;
600616 if exclusive_mode {
601617 // In exclusive mode, only reconnect to originally specified peers
602618 for addr in initial_peers. iter ( ) {
@@ -987,6 +1003,7 @@ impl Clone for MultiPeerNetworkManager {
9871003 peers_sent_headers2 : self . peers_sent_headers2 . clone ( ) ,
9881004 user_agent : self . user_agent . clone ( ) ,
9891005 exclusive_mode : self . exclusive_mode ,
1006+ connected_peer_count : self . connected_peer_count . clone ( ) ,
9901007 }
9911008 }
9921009}
@@ -1068,19 +1085,13 @@ impl NetworkManager for MultiPeerNetworkManager {
10681085 }
10691086
10701087 fn is_connected ( & self ) -> bool {
1071- // We're "connected" if we have at least one peer
1072- let pool = self . pool . clone ( ) ;
1073- let count = tokio:: task:: block_in_place ( move || {
1074- tokio:: runtime:: Handle :: current ( ) . block_on ( pool. connection_count ( ) )
1075- } ) ;
1076- count > 0
1088+ // Use cached counter to avoid blocking in async context
1089+ self . connected_peer_count . load ( Ordering :: Relaxed ) > 0
10771090 }
10781091
10791092 fn peer_count ( & self ) -> usize {
1080- let pool = self . pool . clone ( ) ;
1081- tokio:: task:: block_in_place ( move || {
1082- tokio:: runtime:: Handle :: current ( ) . block_on ( pool. connection_count ( ) )
1083- } )
1093+ // Use cached counter to avoid blocking in async context
1094+ self . connected_peer_count . load ( Ordering :: Relaxed )
10841095 }
10851096
10861097 fn peer_info ( & self ) -> Vec < PeerInfo > {
0 commit comments