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
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use std::io::prelude::*;
use std::fs::File;

use cpu::Cpu;
use util;

#[derive(Clone, Debug)]
pub struct Node {
	id: usize,
	cpus: Vec<Cpu>,
	mem_free: u64,
	mem_total: u64,
	mem_used: u64,
	hugepages_2m_free: usize,
	hugepages_2m_total: usize,
	hugepages_1g_free: usize,
	hugepages_1g_total: usize,
}

impl Node {
	pub fn new(id: usize) -> Result<Node, &'static str> {
		let node = Node {
			id: id,
			cpus: Vec::new(),
			mem_free: 0, // TODO: implement
			mem_total: 0, // TODO: implement
			mem_used: 0, // TODO: implement
			hugepages_1g_total: 0,
			hugepages_1g_free: 0,
			hugepages_2m_total: 0,
			hugepages_2m_free: 0,
		};
		node.init()
	}

	fn init(mut self) -> Result<Self, &'static str> {
		if let Ok(_) = util::bitmask_from_hex_file(format!("/sys/devices/system/node/node{}/cpumap", self.id)) {
			for i in 0..4096 {
				if let Ok(mut cpu) = Cpu::new(i) {
					cpu.set_node_id(self.id);
					self.cpus.push(cpu);
				} else {
					break;
				}
			}
			self.mem_init();
			Ok(self)
		} else {
			Err("no node found")
		}
	}

	fn mem_init(&mut self) {
		let path = format!("/sys/devices/system/node/node{}/meminfo", self.id);
		if let Ok(mut f) = File::open(&path) {
			let mut s = String::new();
			if let Ok(_) = f.read_to_string(&mut s) {
				for l in s.lines() {
					let tokens: Vec<&str> = l.split_whitespace().collect();
					match tokens[2] {
						"MemTotal:" => {
							self.mem_total = tokens[3].parse().unwrap_or(0);
						},
						"MemUsed:" => {
							self.mem_used = tokens[3].parse().unwrap_or(0);
						},
						"MemFree:" => {
							self.mem_free = tokens[3].parse().unwrap_or(0);
						},
						_ => {}
					}
				}
			}
		}
		self.hugepages_2m_free = util::usize_from_file(format!("/sys/devices/system/node/node{}/hugepages/hugepages-2048kB/free_hugepages", self.id)).unwrap_or(0);
		self.hugepages_2m_total = util::usize_from_file(format!("/sys/devices/system/node/node{}/hugepages/hugepages-2048kB/nr_hugepages", self.id)).unwrap_or(0);
		self.hugepages_1g_free = util::usize_from_file(format!("/sys/devices/system/node/node{}/hugepages/hugepages-1048576kB/free_hugepages", self.id)).unwrap_or(0);
		self.hugepages_1g_total = util::usize_from_file(format!("/sys/devices/system/node/node{}/hugepages/hugepages-1048576kB/nr_hugepages", self.id)).unwrap_or(0);
	}

	pub fn id(&self) -> usize {
		self.id
	}

	pub fn cpus(&self) -> &Vec<Cpu> {
		&self.cpus
	}

	pub fn mem_free(&self) -> u64 {
		self.mem_free
	}

	pub fn mem_total(&self) -> u64 {
		self.mem_total
	}

	pub fn mem_used(&self) -> u64 {
		self.mem_used
	}

	pub fn hugepages_2m_free(&self) -> usize {
		self.hugepages_2m_free
	}

	pub fn hugepages_2m_total(&self) -> usize {
		self.hugepages_2m_total
	}

	pub fn hugepages_1g_free(&self) -> usize {
		self.hugepages_1g_free
	}

	pub fn hugepages_1g_total(&self) -> usize {
		self.hugepages_1g_total
	}
}