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