1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker //! Encapsulate the main runtime loop of a metrics process. 6*bb4ee6a4SAndroid Build Coastguard Worker 7*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Result; 8*bb4ee6a4SAndroid Build Coastguard Worker use base::info; 9*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken; 10*bb4ee6a4SAndroid Build Coastguard Worker use base::RecvTube; 11*bb4ee6a4SAndroid Build Coastguard Worker 12*bb4ee6a4SAndroid Build Coastguard Worker use crate::RequestHandler; 13*bb4ee6a4SAndroid Build Coastguard Worker 14*bb4ee6a4SAndroid Build Coastguard Worker /// Runs the metrics controller. 15*bb4ee6a4SAndroid Build Coastguard Worker pub struct MetricsController { 16*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) agents: Vec<RecvTube>, 17*bb4ee6a4SAndroid Build Coastguard Worker handler: RequestHandler, 18*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) closed_tubes: usize, 19*bb4ee6a4SAndroid Build Coastguard Worker } 20*bb4ee6a4SAndroid Build Coastguard Worker 21*bb4ee6a4SAndroid Build Coastguard Worker #[derive(EventToken)] 22*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) enum MetricsControllerToken { 23*bb4ee6a4SAndroid Build Coastguard Worker /// Triggered when the agent's pipe is readable (e.g. read_notifier). 24*bb4ee6a4SAndroid Build Coastguard Worker Agent(usize), 25*bb4ee6a4SAndroid Build Coastguard Worker /// Triggered when the agent's pipe closes (e.g. close_notifier). 26*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] 27*bb4ee6a4SAndroid Build Coastguard Worker AgentExited(usize), 28*bb4ee6a4SAndroid Build Coastguard Worker } 29*bb4ee6a4SAndroid Build Coastguard Worker 30*bb4ee6a4SAndroid Build Coastguard Worker impl MetricsController { new(agents: Vec<RecvTube>) -> Self31*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(agents: Vec<RecvTube>) -> Self { 32*bb4ee6a4SAndroid Build Coastguard Worker Self { 33*bb4ee6a4SAndroid Build Coastguard Worker agents, 34*bb4ee6a4SAndroid Build Coastguard Worker handler: RequestHandler::new(), 35*bb4ee6a4SAndroid Build Coastguard Worker closed_tubes: 0, 36*bb4ee6a4SAndroid Build Coastguard Worker } 37*bb4ee6a4SAndroid Build Coastguard Worker } 38*bb4ee6a4SAndroid Build Coastguard Worker 39*bb4ee6a4SAndroid Build Coastguard Worker /// Run the metrics controller until all clients exit & close their Tubes. run(&mut self) -> Result<()>40*bb4ee6a4SAndroid Build Coastguard Worker pub fn run(&mut self) -> Result<()> { 41*bb4ee6a4SAndroid Build Coastguard Worker self.run_internal()?; 42*bb4ee6a4SAndroid Build Coastguard Worker self.handler.shutdown(); 43*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 44*bb4ee6a4SAndroid Build Coastguard Worker } 45*bb4ee6a4SAndroid Build Coastguard Worker 46*bb4ee6a4SAndroid Build Coastguard Worker /// Handles a tube that has indicated it has data ready to read. on_tube_readable(&self, client: &RecvTube)47*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn on_tube_readable(&self, client: &RecvTube) { 48*bb4ee6a4SAndroid Build Coastguard Worker self.handler.handle_tube_readable(client) 49*bb4ee6a4SAndroid Build Coastguard Worker } 50*bb4ee6a4SAndroid Build Coastguard Worker 51*bb4ee6a4SAndroid Build Coastguard Worker /// Handles a closed connection, and returns a bool indicating 52*bb4ee6a4SAndroid Build Coastguard Worker /// whether the run loop itself should close. on_connection_closed(&mut self) -> bool53*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn on_connection_closed(&mut self) -> bool { 54*bb4ee6a4SAndroid Build Coastguard Worker self.closed_tubes += 1; 55*bb4ee6a4SAndroid Build Coastguard Worker info!( 56*bb4ee6a4SAndroid Build Coastguard Worker "metrics tube closed: {} out of {} closed", 57*bb4ee6a4SAndroid Build Coastguard Worker self.closed_tubes, 58*bb4ee6a4SAndroid Build Coastguard Worker self.agents.len(), 59*bb4ee6a4SAndroid Build Coastguard Worker ); 60*bb4ee6a4SAndroid Build Coastguard Worker if self.closed_tubes == self.agents.len() { 61*bb4ee6a4SAndroid Build Coastguard Worker info!("metrics run loop exiting: all tubes closed"); 62*bb4ee6a4SAndroid Build Coastguard Worker return true; 63*bb4ee6a4SAndroid Build Coastguard Worker } 64*bb4ee6a4SAndroid Build Coastguard Worker 65*bb4ee6a4SAndroid Build Coastguard Worker false 66*bb4ee6a4SAndroid Build Coastguard Worker } 67*bb4ee6a4SAndroid Build Coastguard Worker } 68