From 42ee1bafbd7ae8bc6448663f6d8897307717346e Mon Sep 17 00:00:00 2001 From: Tim Zhang Date: Thu, 3 Dec 2020 17:27:50 +0800 Subject: [PATCH] Make Cgroup can be stored in struct - Change type of hier to remove lifetimes - impl Clone, Default, Debug for Cgroup Signed-off-by: Tim Zhang --- src/cgroup.rs | 51 ++++++++++++---------- src/cgroup_builder.rs | 98 +++++++++++++++++++++---------------------- src/hierarchies.rs | 8 ++-- src/lib.rs | 6 +-- 4 files changed, 85 insertions(+), 78 deletions(-) diff --git a/src/cgroup.rs b/src/cgroup.rs index 9a7e859..3e92757 100644 --- a/src/cgroup.rs +++ b/src/cgroup.rs @@ -28,16 +28,37 @@ use std::path::{Path, PathBuf}; /// > specialized behaviour. /// /// This crate is an attempt at providing a Rust-native way of managing these cgroups. -pub struct Cgroup<'b> { +#[derive(Debug)] +pub struct Cgroup { /// The list of subsystems that control this cgroup subsystems: Vec, /// The hierarchy. - hier: &'b dyn Hierarchy, + hier: Box, path: String, } -impl<'b> Cgroup<'b> { +impl Clone for Cgroup { + fn clone(&self) -> Self { + Cgroup { + subsystems: self.subsystems.clone(), + path: self.path.clone(), + hier: crate::hierarchies::auto(), + } + } +} + +impl Default for Cgroup { + fn default() -> Self { + Cgroup { + subsystems: Vec::new(), + hier: crate::hierarchies::auto(), + path: "".to_string(), + } + } +} + +impl Cgroup { /// Create this control group. fn create(&self) { if self.hier.v2() { @@ -56,10 +77,7 @@ impl<'b> Cgroup<'b> { /// Create a new control group in the hierarchy `hier`, with name `path`. /// /// Returns a handle to the control group that can be used to manipulate it. - /// - /// Note that if the handle goes out of scope and is dropped, the control group is _not_ - /// destroyed. - pub fn new>(hier: &dyn Hierarchy, path: P) -> Cgroup { + pub fn new>(hier: Box, path: P) -> Cgroup { let cg = Cgroup::load(hier, path); cg.create(); cg @@ -68,11 +86,8 @@ impl<'b> Cgroup<'b> { /// Create a new control group in the hierarchy `hier`, with name `path` and `relative_paths` /// /// Returns a handle to the control group that can be used to manipulate it. - /// - /// Note that if the handle goes out of scope and is dropped, the control group is _not_ - /// destroyed. pub fn new_with_relative_paths>( - hier: &dyn Hierarchy, + hier: Box, path: P, relative_paths: HashMap, ) -> Cgroup { @@ -85,10 +100,7 @@ impl<'b> Cgroup<'b> { /// /// Returns a handle to the control group (that possibly does not exist until `create()` has /// been called on the cgroup. - /// - /// Note that if the handle goes out of scope and is dropped, the control group is _not_ - /// destroyed. - pub fn load>(hier: &dyn Hierarchy, path: P) -> Cgroup { + pub fn load>(hier: Box, path: P) -> Cgroup { let path = path.as_ref(); let mut subsystems = hier.subsystems(); if path.as_os_str() != "" { @@ -101,7 +113,7 @@ impl<'b> Cgroup<'b> { let cg = Cgroup { path: path.to_str().unwrap().to_string(), subsystems: subsystems, - hier: hier, + hier, }; cg @@ -111,11 +123,8 @@ impl<'b> Cgroup<'b> { /// /// Returns a handle to the control group (that possibly does not exist until `create()` has /// been called on the cgroup. - /// - /// Note that if the handle goes out of scope and is dropped, the control group is _not_ - /// destroyed. pub fn load_with_relative_paths>( - hier: &dyn Hierarchy, + hier: Box, path: P, relative_paths: HashMap, ) -> Cgroup { @@ -141,7 +150,7 @@ impl<'b> Cgroup<'b> { let cg = Cgroup { subsystems: subsystems, - hier: hier, + hier, path: path.to_str().unwrap().to_string(), }; diff --git a/src/cgroup_builder.rs b/src/cgroup_builder.rs index afe7387..244ca4a 100644 --- a/src/cgroup_builder.rs +++ b/src/cgroup_builder.rs @@ -77,59 +77,57 @@ macro_rules! gen_setter { } /// A control group builder instance -pub struct CgroupBuilder<'a> { +pub struct CgroupBuilder { name: String, - hierarchy: Box<&'a dyn Hierarchy>, /// Internal, unsupported field: use the associated builders instead. resources: Resources, } -impl<'a> CgroupBuilder<'a> { +impl CgroupBuilder { /// Start building a control group with the supplied hierarchy and name pair. /// /// Note that this does not actually create the control group until `build()` is called. - pub fn new(name: &'a str, hierarchy: Box<&'a dyn Hierarchy>) -> CgroupBuilder<'a> { + pub fn new(name: &str) -> CgroupBuilder { CgroupBuilder { name: name.to_owned(), - hierarchy: hierarchy, resources: Resources::default(), } } /// Builds the memory resources of the control group. - pub fn memory(self) -> MemoryResourceBuilder<'a> { + pub fn memory(self) -> MemoryResourceBuilder { MemoryResourceBuilder { cgroup: self } } /// Builds the pid resources of the control group. - pub fn pid(self) -> PidResourceBuilder<'a> { + pub fn pid(self) -> PidResourceBuilder { PidResourceBuilder { cgroup: self } } /// Builds the cpu resources of the control group. - pub fn cpu(self) -> CpuResourceBuilder<'a> { + pub fn cpu(self) -> CpuResourceBuilder { CpuResourceBuilder { cgroup: self } } /// Builds the devices resources of the control group, disallowing or /// allowing access to certain devices in the system. - pub fn devices(self) -> DeviceResourceBuilder<'a> { + pub fn devices(self) -> DeviceResourceBuilder { DeviceResourceBuilder { cgroup: self } } /// Builds the network resources of the control group, setting class id, or /// various priorities on networking interfaces. - pub fn network(self) -> NetworkResourceBuilder<'a> { + pub fn network(self) -> NetworkResourceBuilder { NetworkResourceBuilder { cgroup: self } } /// Builds the hugepage/hugetlb resources available to the control group. - pub fn hugepages(self) -> HugepagesResourceBuilder<'a> { + pub fn hugepages(self) -> HugepagesResourceBuilder { HugepagesResourceBuilder { cgroup: self } } /// Builds the block I/O resources available for the control group. - pub fn blkio(self) -> BlkIoResourcesBuilder<'a> { + pub fn blkio(self) -> BlkIoResourcesBuilder { BlkIoResourcesBuilder { cgroup: self, throttling_iops: false, @@ -137,19 +135,19 @@ impl<'a> CgroupBuilder<'a> { } /// Finalize the control group, consuming the builder and creating the control group. - pub fn build(self) -> Cgroup<'a> { - let cg = Cgroup::new(*self.hierarchy, self.name); + pub fn build(self, hier: Box) -> Cgroup { + let cg = Cgroup::new(hier, self.name); let _ret = cg.apply(&self.resources); cg } } /// A builder that configures the memory controller of a control group. -pub struct MemoryResourceBuilder<'a> { - cgroup: CgroupBuilder<'a>, +pub struct MemoryResourceBuilder { + cgroup: CgroupBuilder, } -impl<'a> MemoryResourceBuilder<'a> { +impl MemoryResourceBuilder { gen_setter!( memory, MemController, @@ -182,17 +180,17 @@ impl<'a> MemoryResourceBuilder<'a> { gen_setter!(memory, MemController, set_swappiness, swappiness, u64); /// Finish the construction of the memory resources of a control group. - pub fn done(self) -> CgroupBuilder<'a> { + pub fn done(self) -> CgroupBuilder { self.cgroup } } /// A builder that configures the pid controller of a control group. -pub struct PidResourceBuilder<'a> { - cgroup: CgroupBuilder<'a>, +pub struct PidResourceBuilder { + cgroup: CgroupBuilder, } -impl<'a> PidResourceBuilder<'a> { +impl PidResourceBuilder { gen_setter!( pid, PidController, @@ -202,17 +200,17 @@ impl<'a> PidResourceBuilder<'a> { ); /// Finish the construction of the pid resources of a control group. - pub fn done(self) -> CgroupBuilder<'a> { + pub fn done(self) -> CgroupBuilder { self.cgroup } } /// A builder that configures the cpuset & cpu controllers of a control group. -pub struct CpuResourceBuilder<'a> { - cgroup: CgroupBuilder<'a>, +pub struct CpuResourceBuilder { + cgroup: CgroupBuilder, } -impl<'a> CpuResourceBuilder<'a> { +impl CpuResourceBuilder { gen_setter!(cpu, CpuSetController, set_cpus, cpus, String); gen_setter!(cpu, CpuSetController, set_mems, mems, String); gen_setter!(cpu, CpuController, set_shares, shares, u64); @@ -222,17 +220,17 @@ impl<'a> CpuResourceBuilder<'a> { gen_setter!(cpu, CpuController, set_rt_period, realtime_period, u64); /// Finish the construction of the cpu resources of a control group. - pub fn done(self) -> CgroupBuilder<'a> { + pub fn done(self) -> CgroupBuilder { self.cgroup } } /// A builder that configures the devices controller of a control group. -pub struct DeviceResourceBuilder<'a> { - cgroup: CgroupBuilder<'a>, +pub struct DeviceResourceBuilder { + cgroup: CgroupBuilder, } -impl<'a> DeviceResourceBuilder<'a> { +impl DeviceResourceBuilder { /// Restrict (or allow) a device to the tasks inside the control group. pub fn device( mut self, @@ -241,7 +239,7 @@ impl<'a> DeviceResourceBuilder<'a> { devtype: crate::devices::DeviceType, allow: bool, access: Vec, - ) -> DeviceResourceBuilder<'a> { + ) -> DeviceResourceBuilder { self.cgroup.resources.devices.devices.push(DeviceResource { major, minor, @@ -253,22 +251,22 @@ impl<'a> DeviceResourceBuilder<'a> { } /// Finish the construction of the devices resources of a control group. - pub fn done(self) -> CgroupBuilder<'a> { + pub fn done(self) -> CgroupBuilder { self.cgroup } } /// A builder that configures the net_cls & net_prio controllers of a control group. -pub struct NetworkResourceBuilder<'a> { - cgroup: CgroupBuilder<'a>, +pub struct NetworkResourceBuilder { + cgroup: CgroupBuilder, } -impl<'a> NetworkResourceBuilder<'a> { +impl NetworkResourceBuilder { gen_setter!(network, NetclsController, set_class, class_id, u64); /// Set the priority of the tasks when operating on a networking device defined by `name` to be /// `priority`. - pub fn priority(mut self, name: String, priority: u64) -> NetworkResourceBuilder<'a> { + pub fn priority(mut self, name: String, priority: u64) -> NetworkResourceBuilder { self.cgroup .resources .network @@ -278,19 +276,19 @@ impl<'a> NetworkResourceBuilder<'a> { } /// Finish the construction of the network resources of a control group. - pub fn done(self) -> CgroupBuilder<'a> { + pub fn done(self) -> CgroupBuilder { self.cgroup } } /// A builder that configures the hugepages controller of a control group. -pub struct HugepagesResourceBuilder<'a> { - cgroup: CgroupBuilder<'a>, +pub struct HugepagesResourceBuilder { + cgroup: CgroupBuilder, } -impl<'a> HugepagesResourceBuilder<'a> { +impl HugepagesResourceBuilder { /// Limit the usage of certain hugepages (determined by `size`) to be at most `limit` bytes. - pub fn limit(mut self, size: String, limit: u64) -> HugepagesResourceBuilder<'a> { + pub fn limit(mut self, size: String, limit: u64) -> HugepagesResourceBuilder { self.cgroup .resources .hugepages @@ -300,18 +298,18 @@ impl<'a> HugepagesResourceBuilder<'a> { } /// Finish the construction of the network resources of a control group. - pub fn done(self) -> CgroupBuilder<'a> { + pub fn done(self) -> CgroupBuilder { self.cgroup } } /// A builder that configures the blkio controller of a control group. -pub struct BlkIoResourcesBuilder<'a> { - cgroup: CgroupBuilder<'a>, +pub struct BlkIoResourcesBuilder { + cgroup: CgroupBuilder, throttling_iops: bool, } -impl<'a> BlkIoResourcesBuilder<'a> { +impl BlkIoResourcesBuilder { gen_setter!(blkio, BlkIoController, set_weight, weight, u16); gen_setter!(blkio, BlkIoController, set_leaf_weight, leaf_weight, u16); @@ -322,7 +320,7 @@ impl<'a> BlkIoResourcesBuilder<'a> { minor: u64, weight: Option, leaf_weight: Option, - ) -> BlkIoResourcesBuilder<'a> { + ) -> BlkIoResourcesBuilder { self.cgroup .resources .blkio @@ -337,19 +335,19 @@ impl<'a> BlkIoResourcesBuilder<'a> { } /// Start configuring the I/O operations per second metric. - pub fn throttle_iops(mut self) -> BlkIoResourcesBuilder<'a> { + pub fn throttle_iops(mut self) -> BlkIoResourcesBuilder { self.throttling_iops = true; self } /// Start configuring the bytes per second metric. - pub fn throttle_bps(mut self) -> BlkIoResourcesBuilder<'a> { + pub fn throttle_bps(mut self) -> BlkIoResourcesBuilder { self.throttling_iops = false; self } /// Limit the read rate of the current metric for a certain device. - pub fn read(mut self, major: u64, minor: u64, rate: u64) -> BlkIoResourcesBuilder<'a> { + pub fn read(mut self, major: u64, minor: u64, rate: u64) -> BlkIoResourcesBuilder { let throttle = BlkIoDeviceThrottleResource { major, minor, rate }; if self.throttling_iops { self.cgroup @@ -368,7 +366,7 @@ impl<'a> BlkIoResourcesBuilder<'a> { } /// Limit the write rate of the current metric for a certain device. - pub fn write(mut self, major: u64, minor: u64, rate: u64) -> BlkIoResourcesBuilder<'a> { + pub fn write(mut self, major: u64, minor: u64, rate: u64) -> BlkIoResourcesBuilder { let throttle = BlkIoDeviceThrottleResource { major, minor, rate }; if self.throttling_iops { self.cgroup @@ -387,7 +385,7 @@ impl<'a> BlkIoResourcesBuilder<'a> { } /// Finish the construction of the blkio resources of a control group. - pub fn done(self) -> CgroupBuilder<'a> { + pub fn done(self) -> CgroupBuilder { self.cgroup } } diff --git a/src/hierarchies.rs b/src/hierarchies.rs index 4e0742f..fb06cb0 100644 --- a/src/hierarchies.rs +++ b/src/hierarchies.rs @@ -32,10 +32,12 @@ use crate::{Controllers, Hierarchy, Subsystem}; use crate::cgroup::Cgroup; /// The standard, original cgroup implementation. Often referred to as "cgroupv1". +#[derive(Debug)] pub struct V1 { mountinfo: Vec, } +#[derive(Debug)] pub struct V2 { root: String, } @@ -98,8 +100,7 @@ impl Hierarchy for V1 { } fn root_control_group(&self) -> Cgroup { - let b: &dyn Hierarchy = self as &dyn Hierarchy; - Cgroup::load(&*b, "".to_string()) + Cgroup::load(auto(), "".to_string()) } fn root(&self) -> PathBuf { @@ -170,8 +171,7 @@ impl Hierarchy for V2 { } fn root_control_group(&self) -> Cgroup { - let b: &dyn Hierarchy = self as &dyn Hierarchy; - Cgroup::load(&*b, "".to_string()) + Cgroup::load(auto(), "".to_string()) } fn root(&self) -> PathBuf { diff --git a/src/lib.rs b/src/lib.rs index cd53081..46551cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,7 +71,7 @@ use crate::systemd::SystemdController; pub use crate::cgroup::Cgroup; /// Contains all the subsystems that are available in this crate. -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Subsystem { /// Controller for the `Pid` subsystem, see `PidController` for more information. Pid(PidController), @@ -104,7 +104,7 @@ pub enum Subsystem { } #[doc(hidden)] -#[derive(Eq, PartialEq, Debug)] +#[derive(Eq, PartialEq, Debug, Clone)] pub enum Controllers { Pids, Mem, @@ -357,7 +357,7 @@ pub trait ControllIdentifier { /// Control group hierarchy (right now, only V1 is supported, but in the future Unified will be /// implemented as well). -pub trait Hierarchy { +pub trait Hierarchy: std::fmt::Debug + Send { /// Returns what subsystems are supported by the hierarchy. fn subsystems(&self) -> Vec;