metrics/
controller.rs

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
7use anyhow::Result;
8use base::info;
9use base::EventToken;
10use base::RecvTube;
11
12use crate::RequestHandler;
13
14/// Runs the metrics controller.
15pub struct MetricsController {
16    pub(crate) agents: Vec<RecvTube>,
17    handler: RequestHandler,
18    pub(crate) closed_tubes: usize,
19}
20
21#[derive(EventToken)]
22pub(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
30impl MetricsController {
31    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.
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.
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.
53    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}