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