xref: /aosp_15_r20/external/crosvm/metrics/src/controller.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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